首页 > 解决方案 > R - 当两列或多列连续匹配时,在数据框中创建新列

问题描述

我目前被困在我感觉直观的代码的一部分上,但我想不出办法来做到这一点。我有一个非常大的数据框(nrows = 34036,ncol = 43),我想在其中创建变量的连续序列,其中行的值为 1(没有多列和 1)。它仅由零和类似于以下的零组成:

A B C D
1 0 0 0
0 0 0 1
0 0 0 1
0 0 0 0
0 0 0 0
1 0 1 0
1 0 1 0
0 1 0 0
0 1 0 0
1 0 0 1

我能够使用以下方法删除零:

#find the sum of each row
placeholderData <- transform(placeholderData, sum=rowSums(placeholderData)) 
placeholderData <- placeholderData[!(placeholderData$sum <= 0),]

数据框现在看起来像:

A B C D sum
1 0 0 0  1
0 0 0 1  1
0 0 0 1  1
1 0 1 0  2
1 0 1 0  2
0 1 0 0  1
0 1 0 0  1
1 0 0 1  2 

当连续有两个或更多 1 时,我的主要问题就出现了。为了解决这个问题,我使用以下代码来识别总和为 2 或更多的列:

placeholderData$Matches <- lapply(apply(placeholderData == 1, 1, which), names)

它将以下列添加到数据框中:

A B C D sum   Matches
1 0 0 0  1      A
0 0 0 1  1      D
0 0 0 1  1      D
1 0 1 0  2  c("A","C")
1 0 1 0  2  c("A","C")
0 1 0 0  1      B
0 1 0 0  1      B
1 0 0 1  2  c("A", "D")

我添加了 Matches 列作为解决问题的一种方法,但我不确定如果不使用大量逻辑运算符我该怎么做(我不知道哪些列有匹配项)。我想做的是将超过(或等于)两个 1 的行聚合到一个新列中,以便能够拥有这样的数据框:

A B C D AC AD sum   Matches
1 0 0 0 0  0  1      A
0 0 0 1 0  0  1      D
0 0 0 1 0  0  1      D
0 0 0 0 1  0  1  c("A","C")
0 0 0 0 1  0  1  c("A","C")
0 1 0 0 0  0  1      B
0 1 0 0 0  0  1      B
0 0 0 0 0  1  1  c("A", "D")

然后,我将能够正常使用我的代码(当行中没有重复值时它工作得很好)。我试图寻找类似的问题,但我不确定我是否问对了问题。我想知道是否有人可以提供一些帮助或一些我可以尝试的想法。

非常感谢!

标签: rapplylapply

解决方案


这看起来很像制作虚拟变量,所以我会使用model.matrix通常用于虚拟变量的函数(one-hot encoding):

m = read.table(header = T, text = "A B C D
1 0 0 0
0 0 0 1
0 0 0 1
0 0 0 0
0 0 0 0
1 0 1 0
1 0 1 0
0 1 0 0
0 1 0 0
1 0 0 1")

m = m[rowSums(m) > 0, ]
d = factor(sapply(apply(m == 1, 1, which), function(x) paste(names(m)[x], collapse = "")))
result = data.frame(model.matrix(~ d + 0))
names(result) = levels(d)
#   A AC AD B D
# 1 1  0  0 0 0
# 2 0  0  0 0 1
# 3 0  0  0 0 1
# 4 0  1  0 0 0
# 5 0  1  0 0 0
# 6 0  0  0 1 0
# 7 0  0  0 1 0
# 8 0  0  1 0 0

推荐阅读