我有一个数据框,其中包含由 1 或 0 表示的标签的个人偏好:
mydata <- data.frame(
ID = c(1:4),
tag1 = c(1, 0, 1, 0),
tag2 = c(0, 0, 0, 0),
tag3 = c(1, 0, 1, 1),
tag4 = c(1, 1, 0, 1),
tag5 = c(0, 1, 1, 1)
)
(我的数据包含的标签远不止 5 个)
对于网络图,我正在寻找一种方法将宽格式数据转换为连续每对 tag=1 之间出现的长格式列表。对于上面的例子,它看起来像这样:
mydata2 <- data.frame(
ID = c(1,1,1,2,3,3,3,4,4,4),
target = c("tag1","tag1","tag3","tag4","tag1","tag1","tag3","tag3","tag3","tag4"),
source = c("tag3","tag4","tag4","tag5","tag3","tag5","tag5","tag4","tag5","tag5")
)
我想使用 tidyr
的 gather()
来实现此目的,但不知道如何将它用于成对的列。我可以为每一对创建新变量并收集这些变量,但对于一长串标签,这将变得不切实际。有没有更优雅的方法来做到这一点?或者甚至是特定的功能?
最佳答案
这是基于 apply()
的答案(将函数应用于每一行)和 combn( ... , 2)
找到所有对。
ll <- apply(mydata,1,
function(x){
if(sum(x[-1])<2)
# otherwise you'll get errors if there are less than two
# elements selected
return(NULL)
tmp = combn(names(x[-1])[ !!(x[-1]) ],# see note below
2) # pairs
# the return value
data.frame(ID = x['ID'],
target = tmp[1,],
source = tmp[2,],
# otherwise you get names warning, which is
# annoying.j
check.names=FALSE)
})
# bind the individual results together
do.call(rbind,ll)
#> ID target source
#> 1 tag1 tag3
#> 1 tag1 tag4
#> 1 tag3 tag4
#> 2 tag4 tag5
#> 3 tag1 tag3
#> 3 tag1 tag5
#> 3 tag3 tag5
#> 4 tag3 tag4
#> 4 tag3 tag5
#> 4 tag4 tag5
请注意!!x
是一个标准的 JavaScript 技巧,用于将值强制为
逻辑,这也适用于 R。
关于R:从宽的标签列表到长的连接列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28788700/