【问题标题】:Assign value to group based on condition in column根据列中的条件为组分配值
【发布时间】:2015-11-19 18:52:23
【问题描述】:

我有一个如下所示的数据框:

> df = data.frame(group = c(1,1,1,2,2,2,3,3,3), 
                 date = c(1,2,3,4,5,6,7,8,9),
                 value = c(3,4,3,4,5,6,6,4,9))
> df
  group date value
1     1    1     3
2     1    2     4
3     1    3     3
4     2    4     4
5     2    5     5
6     2    6     6
7     3    7     6
8     3    8     4
9     3    9     9

我想创建一个新列,其中包含与值列中的值“4”相关联的每个组的日期值。

以下数据框显示了我希望完成的工作。

  group date value newValue
1     1    1     3        2
2     1    2     4        2
3     1    3     3        2
4     2    4     4        4
5     2    5     5        4
6     2    6     6        4
7     3    7     6        8
8     3    8     4        8
9     3    9     9        8

正如我们所见,组 1 具有 newValue“2”,因为这是与值“4”相关联的日期。同样,第二组有newValue 4,第三组有newValue 8。

我认为使用ave() 或一系列dplyr/data.table 函数有一种简单的方法可以做到这一点,但我的许多尝试都没有成功。

【问题讨论】:

    标签: r data-manipulation


    【解决方案1】:

    还有一个base R路径:

    df$newValue <- ave(`names<-`(df$value==4,df$date), df$group, FUN=function(x) as.numeric(names(x)[x]))
    df
       group date value newValue
    1      1    1     3        2
    2      1    2     4        2
    3      1    3     3        2
    4      2    4     4        4
    5      2    5     5        4
    6      2    6     6        4
    7      3    7     6        8
    8      3    8     4        8
    9      3    9     9        8
    10     3   11     7        8
    

    我对可变长度组进行了测试。我将date 列指定为value 等于4 的逻辑索引的名称。然后按组识别值。

    数据

    df = data.frame(group = c(1,1,1,2,2,2,3,3,3,3), 
                     date = c(1,2,3,4,5,6,7,8,9,11),
                     value = c(3,4,3,4,5,6,6,4,9,7))
    

    【讨论】:

      【解决方案2】:

      这是一个基本的 R 选项

       df$newValue = rep(df$date[which(df$value == 4)], table(df$group))
      

      使用lapply的另一种选择

      do.call(rbind, lapply(split(df, df$group), 
        function(x){x$newValue = rep(x$date[which(x$value == 4)], 
                          each = length(x$group)); x}))
      
      #    group date value newValue
      #1.1     1    1     3        2
      #1.2     1    2     4        2
      #1.3     1    3     3        2
      #2.4     2    4     4        4
      #2.5     2    5     5        4
      #2.6     2    6     6        4
      #3.7     3    7     6        8
      #3.8     3    8     4        8
      #3.9     3    9     9        8
      

      【讨论】:

        【解决方案3】:

        这是一个快速的data.table 一个

        library(data.table)
        setDT(df)[, newValue := date[value == 4L], by = group]
        df
        #    group date value newValue
        # 1:     1    1     3        2
        # 2:     1    2     4        2
        # 3:     1    3     3        2
        # 4:     2    4     4        4
        # 5:     2    5     5        4
        # 6:     2    6     6        4
        # 7:     3    7     6        8
        # 8:     3    8     4        8
        # 9:     3    9     9        8
        

        这是一个类似的dplyr 版本

        library(dplyr)
        df %>%
          group_by(group) %>%
          mutate(newValue = date[value == 4L])
        

        或者在过滤数据后使用merge 的可能的基本 R 解决方案(之后需要一些重命名)

        merge(df, df[df$value == 4, c("group", "date")], by = "group")
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-03-23
        • 2018-07-10
        • 1970-01-01
        • 1970-01-01
        • 2018-04-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多