我在R中有多个大型数据表。有些列名称出现两次,名称几乎重复:除最后一个字符外,它们是相同的。
例如:
[1] "Genre_Romance" (correct)
[2] "Genre_Sciencefiction" (correct)
[3] "Genre_Sciencefictio" (wrong)
[4] "Genre_Fables" (correct)
[5] "Genre_Fable" (wrong)
Genre_Romance <- c(1, 0, 1, 0, 1)
Genre_Sciencefiction <- c(0, 1, 0, 0, 0)
Genre_Sciencefictio <- c(1, 0, 1, 1, 0)
Genre_Fables <- c(0, 0, 1, 0, 0)
Genre_Fable <- c(0, 0, 0, 0, 1)
dt <- data.table(Genre_Romance, Genre_Sciencefiction, Genre_Sciencefictio, Genre_Fables, Genre_Fable)
现在我想添加几乎相同列名的列值。我想在删除不正确的列时将此总和保存在正确的列名下。这里的解决方案是:
dt[,"Genre_Sciencefiction"] <- dt[,2] + dt[, 3]
dt[,"Genre_Fables"] <- dt[,4] + dt[, 5]
dt[,"Genre_Sciencefictio"] <- NULL
dt[,"Genre_Fable"] <- NULL
dt
Genre_Romance Genre_Sciencefiction Genre_Fables
1 1 0
0 1 0
1 1 1
0 1 0
1 0 1
如您所见,并非每个列名都具有几乎重复的名称(例如“Genre_Romance”)。所以我们只保留第一列。
我尝试用for循环逐个比较列名来解决这个问题,并使用substr()函数将最长的列名称与较短的列名称进行比较,如果它们相同则取总和。但它不能正常工作,并且不是非常友好。
下面的帖子也对我有所帮助,但我不能使用'重复',因为列名不完全相同。 how do I search for columns with same name, add the column values and replace these columns with same name by their sum? Using R
提前致谢。
答案 0 :(得分:2)
这是一个或多或少的基础R解决方案,依赖于agrep
来查找相似的名称。 agrep
允许根据&#34;广义Levenshtein编辑距离进行紧密的字符串匹配。&#34;
# find groups of similar names
groups <- unique(lapply(names(dt), function(i) agrep(i, names(dt), fixed=TRUE, value=TRUE)))
# choose the final names as those that are longest
finalNames <- sapply(groups, function(i) i[which.max(nchar(i))])
我选择在与示例匹配的每个组中保留最长的变量名称,您可以使用which.min
轻松切换到最短名称,或者您可以根据需要进行一些硬编码。
接下来,Reduce
被赋予"+"
运算符,并为lapply
的匹配组提供信息。要计算最大值,请使用max
代替"+"
。使用来自.SDcols
的{{1}}和data.frame选择变量,您可以直接将其提供给组向量。
data.table
@Frank的评论指出,这可以在# produce a new data frame
setNames(data.frame(lapply(groups, function(x) Reduce("+", dt[, .SD, .SDcols=x]))),
finalNames)
的较新(1.10 +,我相信)版本中进行简化,以避免data.table
.SD, .SDcols
要使其成为data.table,只需将# produce a new data frame
setNames(data.frame(lapply(groups, function(x) Reduce("+", dt[, ..x]))), finalNames)
替换为as.data.table或将输出包装在data.frame
中。
要将最后一行转换为setDT
解决方案,您可以使用
data.table
或者,关注@Frank的评论
dtFinal <- setnames(dt[, lapply(groups, function(x) Reduce("+", dt[, .SD, .SDcols=x]))],
finalNames)
都返回
dtFinal <- setnames(dt[, lapply(groups, function(x) Reduce("+", dt[, ..x]))], finalNames)