R - 添加名称几乎相同的列,并使用正确的列名保存

时间:2017-03-14 15:39:51

标签: r duplicates data.table

我在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

提前致谢。

1 个答案:

答案 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)