【问题标题】:Create binary variable based on number of unique / distinct values by group根据组的唯一/不同值的数量创建二进制变量
【发布时间】:2014-12-10 09:03:39
【问题描述】:

我的数据如下:

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)

对于每个“用户 ID”,我想创建一个二进制指示变量,如果有多个唯一产品,则为 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') -> result = 0。用户 2 有多个唯一的产品 ('b' 和 'c') -> result = 1。

【问题讨论】:

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


    【解决方案1】:

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

    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))
    

    【讨论】:

      【解决方案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 并在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 我也收到了警告。但是,后来我想到as.character 或者as.numeric 也适合
      • 您也可以使用transform 添加类似的解决方案,例如transform(df, result = ave(as.character(product), userID, FUN = function(x) length(unique(x)) &gt; 1) + 0))
      • 我工作的那个是tbl &lt;- rowSums(!!table(df[,-3]))&gt;1,第二个命令行改为:(df$userID %in% names(tbl)[tbl])+0
      【解决方案3】:

      这是我的:

      # 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
      

      【讨论】:

        【解决方案4】:

        您可以使用包data.tabledplyr 来解决这种拆分-应用-组合任务。这就是使用data.table 的方法:

        library(data.table)
        setDT(df)    ## convert to the new format
        df[, result:=as.integer(length(unique(product)) > 1), by=userID]
        

        【讨论】:

          猜你喜欢
          • 2022-01-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-19
          • 2019-09-28
          相关资源
          最近更新 更多