【问题标题】:How can I subtract values within one column based on values in mutliple other columns?如何根据多个其他列中的值减去一列中的值?
【发布时间】:2021-01-18 13:04:10
【问题描述】:

我有一个这样的数据框:

dat <- data.frame(c = c(rep(0, 3), rep(5, 3), rep(10, 3)),
                  id = c(rep(c("A","B","C"), 3)),
                  measurement = c(1:8, 1))

dat
#    c id measurement
# 1  0  A           1
# 2  0  B           2
# 3  0  C           3
# 4  5  A           4
# 5  5  B           5
# 6  5  C           6
# 7 10  A           7
# 8 10  B           8
# 9 10  C           1

我想从该列中的所有其他值中减去“测量”列中的值,其中 c 为 0。这应该根据“id”列中给出的信息单独发生。例如。应从 c > 0 且“id”为 A 的所有值中减去 c 为 0 且“id”为 A 的值。应从 c 的所有值中减去 c 为 0 且“id”为 B 的值是 > 0 并且“id”是 B 等等。

如果差值为负,则结果应为 0。

结果应该是这样的:

result <- data.frame(c = c(rep(0, 3), rep(5, 3), rep(10, 3)),
                 id = c(rep(c("A","B","C"), 3)),
                 measurement = c(1:8, 1),
                 difference = c(0,0,0,3,3,3,6,6,0))

result
#    c id measurement difference
# 1  0  A           1          0
# 2  0  B           2          0
# 3  0  C           3          0
# 4  5  A           4          3
# 5  5  B           5          3
# 6  5  C           6          3
# 7 10  A           7          6
# 8 10  B           8          6
# 9 10  C           1          0

我使用 dplyr 根据其他列的信息选择“测量”的值,但不幸的是我不知道如何进行计算。所以欢迎任何建议!

【问题讨论】:

    标签: r dplyr


    【解决方案1】:

    对于每个id,您可以用c = 0 的值减去measurement 值。使用pmax,我们将负值替换为 0。

    library(dplyr)
    
    dat %>%
      group_by(id) %>%
      mutate(difference = pmax(measurement - measurement[c == 0], 0))
    
    #     c id    measurement difference
    #  <dbl> <chr>       <dbl>      <dbl>
    #1     0 A               1          0
    #2     0 B               2          0
    #3     0 C               3          0
    #4     5 A               4          3
    #5     5 B               5          3
    #6     5 C               6          3
    #7    10 A               7          6
    #8    10 B               8          6
    #9    10 C               1          0
    

    【讨论】:

      【解决方案2】:

      试试这个。您可以使用连接并为您定义的过滤器过滤数据。之后dplyr 动词有助于达到预期的输出:

      library(dplyr)
      #Code
      new <- dat %>%
        left_join(
          dat %>% filter(c==0) %>% select(-c) %>% rename(Var=measurement)
        ) %>%
        mutate(measurement=measurement-Var) %>%
        replace(.<=0,0) %>% select(-Var)
      

      输出:

         c id measurement
      1  0  A           0
      2  0  B           0
      3  0  C           0
      4  5  A           3
      5  5  B           3
      6  5  C           3
      7 10  A           6
      8 10  B           6
      9 10  C           0
      

      【讨论】:

      • 也感谢您的解决方案。它也很有效,但我发现 Ronak 的方法更直观。
      • @empetrum 很好,如果你愿意,你可以投票,并认为答案在任何意义上都有帮助。问候。
      最近更新 更多