如何在R中对行的子集进行数据变换

17

我在dplyr中尝试对行子集进行变异但出了问题。我使用链式命令%>%来表示:


data <- data %>%
  filter(ColA == "ABC") %>%
  mutate(ColB = "XXXX")
这个方法运行良好,但问题在于我想选择整个原始表格,并仅查看应用于我指定的数据子集的变异。我的问题是,在此之后查看数据时,我只看到了 data 子集及其更新的 ColB 信息。
我还想知道如何使用data.table完成此操作。
谢谢。

我发现https://dev59.com/HVsX5IYBdhLWcg3wNtPA#34096575提供了一个全面的探索,用于修改选定行。 - Shixiang Wang
4个回答

17

当您使用filter()方法时,实际上是在删除与指定条件不匹配的行,因此它们不会出现在最终数据集中。

ColB是否已经存在于您的数据框中?如果是,则

data %>%
  mutate(ColB = ifelse(ColA == "ABC", "XXXX", ColB))

ColA == "ABC" 时,将会把 ColB 修改为 "XXXX",否则保持原样。如果 ColB 不存在,那么你需要指定在 ColA != "ABC" 的行中应该执行什么操作,例如:

data %>%
  mutate(ColB = ifelse(ColA == "ABC", "XXXX", NA))

15

使用 data.table ,我们可以这样做:

setDT(data)[colA == "ABC", ColB := "XXXX"]

值被原地修改,不同于if-else会把整列复制一遍来替换仅满足条件的行。

我们称之为按引用子赋值。 您可以在新的HTML随笔中了解更多相关信息。


谢谢。这个方法可行。那么如何进行多条件筛选呢?我尝试了以下代码,但似乎语法不正确。setDT(data)[(colA == "ABC") & (colC =="DEF"), ColB := "XXXX"] - mo_maat
@user1991118 那 正确的语法 - 也许你可以展示一个可重现的例子。我唯一能想到的是,也许你想使用 | 而不是 & - eddi
那确实是正确的语法。我使用了错误的变量。它现在可以工作了。 - mo_maat

2

另一个选项是对相同的数据执行联合和反连接的后续组合。这需要一个主键:

data <- data %>%
  filter(ColA == "ABC") %>%
  mutate(ColB = "XXXX") %>%
  rbind_list(., anti_join(data, ., by = ...))

例子:

mtcars_n <- mtcars %>% add_rownames
mtcars_n %>%
  filter(cyl > 6) %>%
  mutate(mpg = 1) %>%
  rbind_list(., anti_join(mtcars_n, ., by = "rowname"))

这种方法比其他任何方法都要慢得多,但可以通过扩展现有的管道来快速获得结果。

1

更新于 (截至2022年6月2日),@krlmlr的回答很好:

add_rownames()已被弃用,请改用tibble::rownames_to_column()rbind_list也已被弃用,请改用bind_rows

你可能会在结果数据集中发现不同顺序的行,这取决于你的目标,使用dplyr::arrange()进行后续更正可能会比较困难。

另一种选择是较慢但可行的:

mtcars_n <- mtcars %>% 
  add_rownames() %>% 
  filter(cyl > 6) %>%
  mutate(new_col = 1)
mtcars_m <- left_join(x=mtcars, y=mtcars_n)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接