根据列中的条件为组赋值

Assign value to group based on condition in column

提问人:Boudewijn Aasman 提问时间:8/26/2015 最后编辑:dpelBoudewijn Aasman 更新时间:7/19/2018 访问量:26871

问:

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

> 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 具有“2”,因为这是与值“4”关联的日期。同样,第二组有 4 个,第三组有 8 个。newValuenewValuenewValue

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

r 数据操作

评论


答:

23赞 David Arenburg 8/26/2015 #1

这是一个快速的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])

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

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

评论

1赞 Boudewijn Aasman 8/26/2015
正是我需要的。谢谢!
0赞 Ashmin Kaul 12/8/2017
@David阿伦堡,请帮我在这里做一些调整,stackoverflow.com/questions/47716479/......
1赞 Veerendra Gadekar 8/26/2015 #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
1赞 Pierre L 8/26/2015 #3

还有一条路: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

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

数据

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