我一直在使用名为daff的包比较R中的两个数据帧,这是我得到的最终表:
dput(df)
structure(list(v1 = c("Silva->Silva/Mark", "Brandon->Brandon/Livo", "Mango->Mango or Apple"),
v2 = c("James->James=Jacy","NA->Na/Jane", "Egg->Egg and Orange")),
class = "data.frame", row.names = c(NA, -3L))
行字段具有->(箭头),表示该单元中的数据已从先前的数据帧列修改为当前数据帧值。现在,从这里开始,我必须用->(arrow)分隔符分隔各列,以便可以有一个旧列和一个新的更改列。这意味着我在新列中添加了后缀 _old 和 _New 。我使用了这段代码,然后看到输出:
setDT(df)
df1<- lapply(names(df), function(x) {
mDT <- df[, tstrsplit(get(x), " *-> *")]
if (ncol(mDT) == 2L) setnames(mDT, paste0(x, c("_Old", "_New")))
}) %>% as.data.table()
输出
dput(df)
structure(list(v1_Old = c("Silva", "Brandon", "Mango"),
v1_New = c("Silva/Mark", "Brandon/Livo", "Mango or Apple"),
v2_Old = c("James","NA", "Egg"),
v2_New = c("James=Jacy","Na/Jane", "Egg and Orange")),
class = "data.frame", row.names = c(NA, -3L))
现在,我的下一步是比较后缀为 _old 和 _new 的每两列,以标识已修改的内容,然后拆分并存储在名为 diff_v1的新列中和 diff_v2 。我确实使用了此代码(意识到,我必须通过创建不同的拆分代码行来手动完成此操作,这对于20多个单独的列而言是乏味的):
df$diff_v1<- mapply(function(x, y) paste(setdiff(y, x), collapse = '| '), strsplit(df$v1_old, '\\||, | | -| \\+'), strsplit(df$v1_Name_new, '\\||, | | -| \\+'))
df$diff_v2<- mapply(function(x, y) paste(setdiff(y, x), collapse = '| '), strsplit(df$v2_old, '\\||, | | -| \\+'), strsplit(df$v2_new, '\\||, | | -| \\+'))
输出
dput(df)
structure(list(v1_Old = c("Silva", "Brandon", "Mango"),
v1_New = c("Silva/Mark", "Brandon/Livo", "Mango or Apple"),
diff_v1 = c("/Mark", "/Livo", "or Apple"),
v2_Old = c("James","NA", "Egg"),
v2_New = c("James=Jacy","Na/Jane", "Egg and Orange"),
diff_v2 = c("=Jacy","/Jane", "and Orange")),
class = "data.frame", row.names = c(NA, -3L))
我的问题是,我是否可以遍历具有 _old 和 _new 的列,并创建名为 diff_v1 和 diff_v2的新列之后,不再逐行运行代码。我有多列,它们根据我正在比较的数据帧不断变化。想知道如何使用代码自动标识后缀为 _Old 和 _New 的列并拆分,然后在两个之后创建该新列,但应该在每对列上进行。
当前,我必须转到数据框,检查旧列和新列,然后手动更改正在拆分并创建 diff列
的代码答案 0 :(得分:0)
我们可以使用"Old"
根据它们的名称来标识"New"
和grep
列。我们可以使用在str_remove
和string
上矢量化的pattern
来删除"Old"
col中存在的"New"
col的一部分,以创建新列。
old_cols <- grep("Old$", names(df), value = TRUE)
new_cols <- grep("New$", names(df), value = TRUE)
df[sub("New$", "diff", new_cols)] <- Map(stringr::str_remove,
df[new_cols], df[old_cols])
要按顺序获取名称,我们可以
df <- df[order(sub("_.*", "", names(df)))]
df
# v1_Old v1_New v1_diff v2_Old v2_New v2_diff
#1 Silva Silva/Mark /Mark James James=Jacy =Jacy
#2 Brandon Brandon/Livo /Livo NA Na/Jane Na/Jane
#3 Mango Mango or Apple or Apple Egg Egg and Orange and Orange
使用tidyverse
,我们可以做到
library(tidyverse)
df %>%
bind_cols(map2(df %>% select(ends_with("New")),
df %>% select(ends_with("Old")), stringr::str_remove))