r为行中的同一用户标记不同的值

时间:2014-10-15 10:13:17

标签: r data-manipulation split-apply-combine

我的数据如下:

userID  <-c(1,1,1,2,2,2,3,3,3)
product <-c("a","a","a","b","b","c","a","b","c")
result  <-c(0,0,0,0,0,0,0,0,0)

df<-data.frame(userID,product,result)

如果用户ID具有不同的产品,我想用1填充结果,如果用户拥有所有相同的产品,我想填写0。

所以我填充的矢量看起来像是:

result<-c(0,0,0,1,1,1,1,1,1)

我不知道如何在没有大量循环的情况下做到这一点,但我知道应该有更快的方法。

4 个答案:

答案 0 :(得分:4)

这是实现这一目标的一种方法

library(data.table)
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))

答案 1 :(得分:2)

您可以使用ave

中的base R
 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并在result

中创建新变量df
  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

答案 2 :(得分: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]

答案 3 :(得分: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