【问题标题】:Speading manipulation on data.frame with dplyr in R在 R 中使用 dplyr 对 data.frame 进行快速操作
【发布时间】:2018-06-18 03:21:03
【问题描述】:

我有一个大的data.frame 结构类似于以下示例df

df <- data.frame(id = c(rep("A",3), rep("B", 2), rep("C", 4)), 
                 x = c(paste0(letters[1:3],1) , paste0(letters[1:2],3), 
                       paste0(letters[1:4], 1)) , 
                 y = 1:9, z = 2:10 )
#   id  x y  z
# 1  A a1 1  2
# 2  A b1 2  3
# 3  A c1 3  4
# 4  B a3 4  5
# 5  B b3 5  6
# 6  C a1 6  7
# 7  C b1 7  8
# 8  C c1 8  9
# 9  C d1 9 10

在真实数据集中有一个额外的维度(时间),并且有更多的数字列。我想通过以下方式使用dplyr 包来操作df(因为这种操作看起来很快)。

  1. 我需要将xyz 值减去等于b1id == A (row = 2) 减去a3 的@9876543@33@ (@9876543434) ) 和 a1 分别为 id == C (row = 6) 和 ABC 的剩余 yz 值。

  2. 删除已减去的行。

生成的 data.frame 将是

#   id  x y  z
# 1  A a1 -1 -1
# 2  A c1 1  1
# 3  B b3 1  1
# 4  C b1 1  1
# 5  C c1 2  2
# 6  C d1 3  3

在真正的data.frame 中,我有多个数字列(为简单起见,我没有显示),因此这些操作应该应用于所有列。注意x 中的代码必须引用id,因为不同的id 可以有相同的x 代码(例如AC)。

我找到了这个可能的解决方案:

df %>%
  mutate(cond = ifelse( (id == "A" & x == "b1") | ( id == "B" & x == "a3" ) | ( id == "C" & x == "a1" ) , 1, 0 ) ) %>%
  group_by(id) %>%
  mutate_at(vars("y", "z"),funs(.-.[cond==1])) %>%
  filter(cond == 0)

它似乎工作。更好/更快的想法?

【问题讨论】:

  • 作为一个建议,第一个 mutate 步骤可以通过使用您的 id/x 对创建一个 data.frame 来替换,然后进行内部连接。
  • 会更快吗?我追求速度.. 愿意接受比我提出的更好的答案
  • 应该很快。它会更简单,更不容易出错。
  • 你能在答案中写下吗?我还在学习dplyr
  • 您愿意接受 data.table 解决方案吗?我可以在那个包中找到一个快速的解决方案

标签: r for-loop dplyr


【解决方案1】:

如果您愿意接受data.table 解决方案,这应该很快:

library(data.table)
setDT(df)
keys <- data.table(id=c("A","B","C"), x=c("b1","a3","a1"))
onv <- c("id","x")
vars <- c("y","z")
df[df[keys, on=onv], on=onv[1], (vars) := .SD[,..vars] - mget(paste0("i.", vars))][!keys, on=onv]

#   id  x  y  z
#1:  A a1 -1 -1
#2:  A c1  1  1
#3:  B b3  1  1
#4:  C b1  1  1
#5:  C c1  2  2
#6:  C d1  3  3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 2018-11-20
    • 2014-08-10
    • 2017-08-11
    相关资源
    最近更新 更多