R中是否有办法通过指定另一个分组var减去一个组中的两行?

时间:2019-12-20 18:31:08

标签: r

说我有这样的东西:

ID = c("a","a","a","a","a", "b","b","b","b","b")
Group = c("1","2","3","4","5", "1","2","3","4","5")
Value = c(3, 4,2,4,3, 6, 1, 8, 9, 10)
df<-data.frame(ID,Group,Value)

我想从ID中的group = 3中减去group = 5,输出列中每个ID都有此差异,如下所示:


   ID Group Value Want
1   a     1     3    1
2   a     2     4    1
3   a     3     2    1
4   a     4     4    1
5   a     5     3    1
6   b     1     6    2
7   b     2     1    2
8   b     3     8    2
9   b     4     9    2
10  b     5    10    2

此外,如果无法进行该计算(即第5组缺失),则“ want”列的NA值将是理想的。

4 个答案:

答案 0 :(得分:2)

由于每个“ ID”只有一个唯一的“组”,因此我们可以进行子设置

library(dplyr)
df %>% 
   group_by(ID) %>% 
    mutate(want = Value[Group == 5] - Value[Group == 3])
# A tibble: 10 x 4
# Groups:   ID [2]
#   ID    Group Value  want
#   <fct> <fct> <dbl> <dbl>
# 1 a     1         3     1
# 2 a     2         4     1
# 3 a     3         2     1
# 4 a     4         4     1
# 5 a     5         3     1
# 6 b     1         6     2
# 7 b     2         1     2
# 8 b     3         8     2
# 9 b     4         9     2
#10 b     5        10     2

如果我们将其转换为数字索引并获取第一个元素,则可以使以上内容更加防错。如果没有TRUE,则使用[1]返回NA

df %>%
   slice(-10) %>%
   group_by(ID) %>% 
   mutate(want = Value[which(Group == 5)[1]] - Value[which(Group == 3)[1]])

或者使用match如果没有匹配项,则返回索引NA,并且具有NA索引的任何内容都会返回NA,随后将返回NA减去(NA -3

df %>% 
    slice(-10) %>% # removing the last row where Group is 10
    group_by(ID) %>%  
    mutate(want = Value[match(5, Group)] - Value[match(3, Group)])

答案 1 :(得分:0)

一种data.table方法:

library(data.table)

setDT(df)[, want := (Value[Group == 5] - Value[Group == 3]), by = .(ID)]

df
#     ID Group Value want
#  1:  a     1     3    1
#  2:  a     2     4    1
#  3:  a     3     2    1
#  4:  a     4     4    1
#  5:  a     5     3    1
#  6:  b     1     6    2
#  7:  b     2     1    2
#  8:  b     3     8    2
#  9:  b     4     9    2
# 10:  b     5    10    2

答案 2 :(得分:0)

这是使用基数R的解决方案。

unsplit(
    lapply(
        split(df, df$ID),
        function(d) {
            x5 = d$Value[d$Group == "5"]
            x5 = ifelse(length(x5) == 1, x5, NA)
            x3 = d$Value[d$Group == "3"]
            x3 = ifelse(length(x3) == 1, x3, NA)
            d$Want = x5 - x3
            d
        }),
    df$ID)

答案 3 :(得分:0)

这是基本的R解决方案

dfout <- Reduce(rbind,
                lapply(split(df,df$ID),
                       function(x) within(x, Want <-diff(subset(Value, Group %in% c("3","5"))))))

如此

> dfout
   ID Group Value Want
1   a     1     3    1
2   a     2     4    1
3   a     3     2    1
4   a     4     4    1
5   a     5     3    1
6   b     1     6    2
7   b     2     1    2
8   b     3     8    2
9   b     4     9    2
10  b     5    10    2