【问题标题】:How to subtract data frame column from another data frame column if condition is met?如果满足条件,如何从另一个数据框列中减去数据框列?
【发布时间】:2018-08-29 14:24:59
【问题描述】:

我有两个简单的数据框,其中包含“word”和“n”列,用于表示某个单词出现的频率。这是一个例子:

df1 <- data.frame(word=c("beautiful","nice","like","good"),n=c(400,378,29,10))
df2 <- data.frame(word=c("beautiful","nice","like","good","wonderful","awesome","sad","happy"),n=c(6000,20,5,150,300,26,17,195))

除了df1 的单词之外,df2 包含更多单词,因此df1 只是df2 的一小部分。

我找到了包含在df1df2 中的单词。如果特定单词包含在 df2 中,现在我想从 df2 中减去 df1 的单词计数,这意味着我想做以下事情:

  • 减去字数:df2$n - df1$n
  • 仅当df1$word 包含在df2$word

我希望我的问题很清楚。

我已经找到了 df1 中也包含在 df2 中的所有单词

df1 %>% filter(df1$word %in% df2$word)

但是,基于 df1 中的单词必须也在 df2 中然后只减去 df2$n - df1$n 的条件,我正在努力使用减法命令

感谢您的帮助!

【问题讨论】:

  • 您的示例与您的问题不符。 df1 中没有词包含在 df2
  • 是的,我意识到很抱歉,现在我改变了它

标签: r dataframe conditional-statements multiple-columns subtraction


【解决方案1】:

这是一个向量化的基本解决方案,其中布尔乘法用于替换 @Rob 的 for-lop 中使用的 if-then 构造:

 df2$n.adjusted <- df2$n - (df2$word %in% df1$word)* # zero if no match
                                 df1$n[ match(df1$word, df2$word) ] # gets order correct
> df2
       word    n n.adjusted
1 beautiful 6000       5600
2      nice   20       -358
3      like    5        -24
4      good  150        140
5 wonderful  300        300
6   awesome   26         26
7       sad   17         17
8     happy  195        195

这是我用来测试的示例,其中 df1 单词的顺序与 df2 中的顺序不同,并且长度不是偶数:

> df1 <-data.frame(word=c("nice","beautiful","like","good"),n=c(378,400,29,10))
> df2 <- data.frame(word=c("beautiful","nice","like","good","wonderful","awesome","sad"),n=c(6000,20,5,150,300,26,17))
> 
>  df1
       word   n
1      nice 378
2 beautiful 400
3      like  29
4      good  10
>  df2
       word    n
1 beautiful 6000
2      nice   20
3      like    5
4      good  150
5 wonderful  300
6   awesome   26
7       sad   17
> df2$n.adjusted <- df2$n - (df2$word %in% df1$word)*df1$n[match(df1$word, df2$word)]
Warning message:
In (df2$word %in% df1$word) * df1$n[match(df1$word, df2$word)] :
  longer object length is not a multiple of shorter object length
> df2
       word    n n.adjusted
1 beautiful 6000       5600
2      nice   20       -358
3      like    5        -24
4      good  150        140
5 wonderful  300        300
6   awesome   26         26
7       sad   17         17

【讨论】:

  • 我对这个解决方案并不完全满意。当不匹配的单词数不等于匹配的单词数时,它会抛出警告(尽管仍然是正确的结果)。
【解决方案2】:

这是一个使用 for 循环和 %in% 运算符的快速解决方案。

df2$diff <- NA
for (i in 1:nrow(df2)) {
  if (df2$word[i] %in%  df1$word[i]) {
    df2$diff[i] <- df2$n[i] - df1$n[i]
  }
}
df2

输出:

> df2
       word    n diff
1 beautiful 6000 5600
2      nice   20 -358
3      like    5  -24
4      good  150  140
5 wonderful  300   NA
6   awesome   26   NA
7       sad   17   NA
8     happy  195   NA

【讨论】:

    【解决方案3】:
    require(dplyr)
     df1 %>% 
      inner_join(df2, by = 'word') %>% 
      mutate(diff = n.y - n.x) %>% 
      select(word, diff)
    

    给予

           word diff
    1 beautiful 5600
    2      nice -358
    3      like  -24
    4      good  140
    

    【讨论】:

    • 非常感谢!效果很好
    • 是否也有可能接收所有单词的数据框,而不是只接收匹配的单词?
    • @Lucinho91 是的,将inner_join 更改为left_join
    • 谢谢,但这对我不起作用:/ 它仍然只给我匹配的单词而不是全部
    • 哦,我以为你的意思是 df1 中的所有单词。要显示 df2 中的所有单词,请使用 right_join。或者对于df1df2 中的所有单词,使用full_join
    【解决方案4】:

    使用merge

    > df.tmp <- merge(df1, df2, by="word", all=TRUE)
    > df.tmp$result <- df.tmp$n.y - df.tmp$n.x
    > df.tmp
           word n.x  n.y result
    1 beautiful 400 6000   5600
    2      good  10  150    140
    3      like  29    5    -24
    4      nice 378   20   -358
    5   awesome  NA   26     NA
    6     happy  NA  195     NA
    7       sad  NA   17     NA
    8 wonderful  NA  300     NA
    

    如果你只想要匹配的单词

    > df.tmp <- merge(df1, df2, by="word")
    > df.tmp$result <- df.tmp$n.y - df.tmp$n.x
    > df.tmp
           word n.x  n.y result
    1 beautiful 400 6000   5600
    2      good  10  150    140
    3      like  29    5    -24
    4      nice 378   20   -358
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-09-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-04
      • 2021-06-29
      • 1970-01-01
      相关资源
      最近更新 更多