【问题标题】:Add/subtract data frame row from another data frame r从另一个数据框 r 中添加/减去数据框行
【发布时间】:2019-08-19 14:26:17
【问题描述】:

我确定以前有人问过这个问题,但我很难找到它。我需要将一个数据框子集化为一行,然后从相应的列中减去这些值。

我确实找到了Subtract values of a single row from all relevant columns in a data frame,它提供了一个解决方案(见下文),但必须有一个更简单的方法,对吧?非常感谢tidyverse 解决方案。

样本

这是一个示例数据框:

df <- as_tibble(matrix(1:9, 3, 3))
## A tibble: 3 x 3
#     V1    V2    V3
#  <int> <int> <int>
#1     1     4     7
#2     2     5     8
#3     3     6     9

减去相同大小的数据帧是没有问题的。

df - df
#  V1 V2 V3
#1  0  0  0
#2  0  0  0
#3  0  0  0

问题

但是当我将df 子集到一行并尝试减去时,它无法减去不均匀的数据帧。我将df 子集化为

df[1, ]
## A tibble: 1 x 3
#     V1    V2    V3
#  <int> <int> <int>
#1     1     4     7

我想要的解决方案将从第一列中的每个值减去 1,从第二列中的每个值中减去 4,从第三列中的每个值中减去 7,结果如下:

## A tibble: 3 x 3
#     V1    V2    V3
#  <int> <int> <int>
#1     0     0     0
#2     1     1     1
#3     2     2     2

尝试这样做会导致错误:

df - df[1, ]
#Error in Ops.data.frame(df, df[1, ]) : 
#  ‘-’ only defined for equally-sized data frames

在上面的链接中,我找到了这个可行的解决方案:

as_tibble(Map(`-`, df, df[1, ]))
## A tibble: 3 x 3
#     V1    V2    V3
#  <int> <int> <int>
#1     0     0     0
#2     1     1     1
#3     2     2     2

但是这个解决方案看起来真的很复杂,并且不容易合并到一系列管道中。

有人有什么想法吗?

【问题讨论】:

  • 你的最后一行isn't easily incorporated into a series of pipes。您希望解决方案看起来如何?
  • @akrun 首选方法类似于 df %&gt;% mutate(. - slice(1)) 。类似的东西。我想使用mutatemutate_all 之类的变体。
  • 好的,我在下面添加了另一个解决方案,请检查
  • @akrun 现在你只是在炫耀。哈!感谢您提供的种类繁多。
  • 你可以使用df %&gt;% mutate_at(2:3, list(~ . - first(.)))

标签: r dplyr


【解决方案1】:

我们可以在数据集的col 索引上复制行基。这使得两个数据集具有相同的长度/维度

df - unlist(df[1,])[col(df)]
#   V1 V2 V3
#1  0  0  0
#2  1  1  1
#3  2  2  2

如果我们需要一个 tidyverse 选项,可以使用map2

library(purrr)
library(dplyr)
map2_df(df, df[1, ], `-`)
# A tibble: 3 x 3
#     V1    V2    V3
#  <int> <int> <int>
#1     0     0     0
#2     1     1     1
#3     2     2     2

或者另一个选项是uncount

df - uncount(df[1, ], nrow(df))

或者使用管道

df %>% 
  slice(1) %>% 
  uncount(nrow(df)) %>%
  {df - .}
#  V1 V2 V3
#1  0  0  0
#2  1  1  1
#3  2  2  2

或者mutate_all

df %>%
    mutate_all(list(~ . - first(.)))
# A tibble: 3 x 3
#     V1    V2    V3
#  <int> <int> <int>
#1     0     0     0
#2     1     1     1
#3     2     2     2

【讨论】:

  • 如果您有兴趣,我对您提供的所有变体进行了基准测试,其中包含一千行测试 df。 map2 是最快的,紧随其后的是 Map。其余的都远远落后。
【解决方案2】:

如果您只是想减去 data.frame 的第一行,那么最好考虑只从每列中减去第一个值。你可以通过dplyr轻松做到这一点

library(dplyr)
df %>% mutate_all(~.-first(.))

【讨论】:

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