按组基于唯一/不同值数量创建二进制变量

3
我有以下数据:

userID  <- c(1,1,1,2,2,2,3,3,3)
product <- c("a","a","a","b","b","c","a","b","c")
df <- data.frame(userID, product)

对于每个“userID”,我想创建一个二元指示变量,如果有多个不同的产品,则为1,如果所有产品都相同,则为0。

因此,我的填充向量将如下所示:

df$result <- c(0,0,0,1,1,1,1,1,1)
#    userID product result
# 1      1       a      0
# 2      1       a      0
# 3      1       a      0
# 4      2       b      1
# 5      2       b      1
# 6      2       c      1
# 7      3       a      1
# 8      3       b      1
# 9      3       c      1

例如,用户1只有一个独特的产品('a')-> 结果=0。 用户2有多个独特的产品('b'和'c')-> 结果=1。

4个回答

5
这里有一种实现的方法。
library(data.table)
setDT(df)[, result := as.integer(uniqueN(product) > 1), by = userID]
# or
# setDT(df)[, result := as.integer(length(unique(product)) > 1), by = userID]
df
#    userID product result
# 1:      1       a      0
# 2:      1       a      0
# 3:      1       a      0
# 4:      2       b      1
# 5:      2       b      1
# 6:      2       c      1
# 7:      3       a      1
# 8:      3       b      1
# 9:      3       c      1

或者

library(dplyr)
df %>%
  group_by(userID) %>%
  mutate(result = as.integer(n_distinct(product) > 1))

3
你可以使用 base R 中的 ave
 df$result <- with(df, ave(as.character(product), userID, 
                 FUN=function(x) length(unique(x)))>1) +0 
 df$result
 [1] 0 0 0 1 1 1 1 1 1

或者像 @David Arenburg 建议的那样,您可以使用 transform 并在 df 中创建一个名为 result 的新变量。

  transform(df, result = (ave(as.character(product), 
          userID, FUN = function(x) length(unique(x)))>1)+0)

或者

tbl <- rowSums(!!table(df[,-3]))>1
(df$userID %in% names(tbl)[tbl])+0
 #[1] 0 0 0 1 1 1 1 1 1

啊,你解开了我为什么无法让“ave”工作的谜团,“as.character”...真是太烦人了。 - David Arenburg
@David Arenburg 我也收到了警告。但是,我想到as.character或者也许as.numeric也可以。 - akrun
1
你也可以尝试使用 transform 添加类似的解决方案,例如 transform(df, result = ave(as.character(product), userID, FUN = function(x) length(unique(x)) > 1) + 0)) - David Arenburg
我成功实现的代码段如下: tbl <- rowSums(!!table(df[,-3]))>1 将第二行代码修改为: (df$userID %in% names(tbl)[tbl])+0 - Daryl

2
您可以使用 data.tabledplyr 包来解决这种分割-应用-合并的任务。以下是使用 data.table 的方法:
library(data.table)
setDT(df)    ## convert to the new format
df[, result:=as.integer(length(unique(product)) > 1), by=userID]

1
这是我的:
# table of users x number_of_products
myTable <- table(userID, product)
# one line from there:
(result <- ifelse(rowSums(myTable!=0)==1, 0, 1)[userID])
1 1 1 2 2 2 3 3 3 
0 0 0 1 1 1 1 1 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接