将多行的组合矩阵放在数据框的一列中,然后将其拆分
Put the combinations matrix of many rows in a column of a dataframe, then split it
我有一个看起来像这样的数据框(我简化了):
df <- data.frame(rbind(c(1, "dog", "cat", "rabbit"), c(2, "apple", "peach", "cucumber")))
colnames(df) <- c("ID", "V1", "V2", "V3")
## ID V1 V2 V3
## 1 1 dog cat rabbit
## 2 2 apple peach cucumber
我想创建一个包含所有可能的变量组合的列 V1:V3 两两(顺序无关紧要),但保留 link 与原始 ID。所以像这样。
## ID bigrams
## 1 1 dog cat
## 2 1 cat rabbit
## 3 1 dog rabbit
## 4 2 apple peach
## 5 2 apple cucumber
## 6 2 peach cucumber
我的想法:使用combn()
、mutate()
和separate_row()
。
library(tidyr)
library(dplyr)
df %>%
mutate(bigrams=paste(unlist(t(combn(df[,2:4],2))), collapse="-")) %>%
separate_rows(bigrams, sep="-") %>%
select(ID,bigrams)
结果不是我所期望的...我想连接一个矩阵(combine()
的结果)并不那么容易。
对此我有两个问题:1) 如何调试这段代码? 2)这是做这种事情的好方法吗?我是 R 的新手,但我有 Open Refine 背景,所以连接拆分多值单元格对我来说很有意义。但这也是 R 的正确方法吗?
在此先感谢您的帮助。
我们可以用 data.table
做到这一点。将'data.frame'转'data.table'(setDT(df)
),melt
转'long'格式,按'ID'分组,得到combn
'value' 和 paste
一起
library(data.table)
dM <- melt(setDT(df), id.var = "ID")[, combn(value, 2, FUN = paste, collapse=' '), ID]
setnames(dM, 2, 'bigrams')[]
# ID bigrams
#1: 1 dog cat
#2: 1 dog rabbit
#3: 1 cat rabbit
#4: 2 apple peach
#5: 2 apple cucumber
#6: 2 peach cucumber
我推荐@akrun 的“melt
优先”方法,但为了好玩,这里有更多方法可以做到这一点:
library(tidyverse)
df %>%
mutate_all(as.character) %>%
transmute(ID = ID, bigrams = pmap(
list(V1, V2, V3),
function(a, b, c) combn(c(a, b, c), 2, paste, collapse = " ")
))
# ID bigrams
# 1 1 dog cat, dog rabbit, cat rabbit
# 2 2 apple peach, apple cucumber, peach cucumber
(mutate_all(as.character)
只是因为你给了我们因子,而因子到字符的转换可能会令人惊讶)。
df %>%
mutate_all(as.character) %>%
nest(-ID) %>%
mutate(bigrams = map(data, combn, 2, paste, collapse = " ")) %>%
unnest(data) %>%
as.data.frame()
# ID bigrams V1 V2 V3
# 1 1 dog cat, dog rabbit, cat rabbit dog cat rabbit
# 2 2 apple peach, apple cucumber, peach cucumber apple peach cucumber
(as.data.frame()
只是为了更漂亮的打印)
我有一个看起来像这样的数据框(我简化了):
df <- data.frame(rbind(c(1, "dog", "cat", "rabbit"), c(2, "apple", "peach", "cucumber")))
colnames(df) <- c("ID", "V1", "V2", "V3")
## ID V1 V2 V3
## 1 1 dog cat rabbit
## 2 2 apple peach cucumber
我想创建一个包含所有可能的变量组合的列 V1:V3 两两(顺序无关紧要),但保留 link 与原始 ID。所以像这样。
## ID bigrams
## 1 1 dog cat
## 2 1 cat rabbit
## 3 1 dog rabbit
## 4 2 apple peach
## 5 2 apple cucumber
## 6 2 peach cucumber
我的想法:使用combn()
、mutate()
和separate_row()
。
library(tidyr)
library(dplyr)
df %>%
mutate(bigrams=paste(unlist(t(combn(df[,2:4],2))), collapse="-")) %>%
separate_rows(bigrams, sep="-") %>%
select(ID,bigrams)
结果不是我所期望的...我想连接一个矩阵(combine()
的结果)并不那么容易。
对此我有两个问题:1) 如何调试这段代码? 2)这是做这种事情的好方法吗?我是 R 的新手,但我有 Open Refine 背景,所以连接拆分多值单元格对我来说很有意义。但这也是 R 的正确方法吗?
在此先感谢您的帮助。
我们可以用 data.table
做到这一点。将'data.frame'转'data.table'(setDT(df)
),melt
转'long'格式,按'ID'分组,得到combn
'value' 和 paste
一起
library(data.table)
dM <- melt(setDT(df), id.var = "ID")[, combn(value, 2, FUN = paste, collapse=' '), ID]
setnames(dM, 2, 'bigrams')[]
# ID bigrams
#1: 1 dog cat
#2: 1 dog rabbit
#3: 1 cat rabbit
#4: 2 apple peach
#5: 2 apple cucumber
#6: 2 peach cucumber
我推荐@akrun 的“melt
优先”方法,但为了好玩,这里有更多方法可以做到这一点:
library(tidyverse)
df %>%
mutate_all(as.character) %>%
transmute(ID = ID, bigrams = pmap(
list(V1, V2, V3),
function(a, b, c) combn(c(a, b, c), 2, paste, collapse = " ")
))
# ID bigrams
# 1 1 dog cat, dog rabbit, cat rabbit
# 2 2 apple peach, apple cucumber, peach cucumber
(mutate_all(as.character)
只是因为你给了我们因子,而因子到字符的转换可能会令人惊讶)。
df %>%
mutate_all(as.character) %>%
nest(-ID) %>%
mutate(bigrams = map(data, combn, 2, paste, collapse = " ")) %>%
unnest(data) %>%
as.data.frame()
# ID bigrams V1 V2 V3
# 1 1 dog cat, dog rabbit, cat rabbit dog cat rabbit
# 2 2 apple peach, apple cucumber, peach cucumber apple peach cucumber
(as.data.frame()
只是为了更漂亮的打印)