我必须加入两个数据框。联接工作正常,我唯一的问题是:
有时我在数据集中有2行,这些行必须与其他数据集连接。连接后,这些行将直接显示在另一行的下方。我需要一排它们:
这是一个小例子:
df1 <- data.frame(A = c(1:5),
B = c(12, 13, 14, 15, 16),
C = c("a", "b", "c", "d", "e"))
df2 <- data.frame(A = c(1,1,2,2,3),
E = c(112, 145, 546, 674, 287),
J = c("t", "e", "v", "p", "s"))
merged <- inner_join(df1, df2, by = "A")
A | B | c | E | J |
---------------------
1 | 12| a | 112 | t
1 | 12| a | 145 | e
2 | 13| b | 546 | v
2 | 13| b | 674 | p
3 | 14| c | 287 | s
我需要这种方式:
A | B | c | E.x | J.x | E.y | J.y
--------------------------------
1 | 12| a | 112 | t | 145 | e
2 | 13| b | 546 | v | 674 | p
在新数据集中的所有行中,所有合并的行都在一起
感谢您的帮助 derlu
**update:**
我的原始数据帧具有
它们被第一列id_merge
合并。有时我有2个匹配项,有时有3个相同的“ id_merge”值。
答案 0 :(得分:1)
一种方法是通过每个键的出现来拆分数据帧,然后进行另一次联接。首先,我们创建一个键(n
)并拆分数据框:
merged <- merged %>%
group_by(A, B, C) %>%
mutate(n = 1:n())
# A B C E J n
# <dbl> <dbl> <fct> <dbl> <fct> <int>
# 1 1 12 a 112 t 1
# 2 1 12 a 145 e 2
# 3 2 13 b 546 v 1
# 4 2 13 b 674 p 2
# 5 3 14 c 287 s 1
merged_list <- split(merged, merged$n) %>%
map(select, -n)
# $`1`
# # A tibble: 3 x 5
# # Groups: A [3]
# A B C E J
# <dbl> <dbl> <fct> <dbl> <fct>
# 1 1 12 a 112 t
# 2 2 13 b 546 v
# 3 3 14 c 287 s
# $`2`
# # A tibble: 2 x 5
# # Groups: A [2]
# A B C E J
# <dbl> <dbl> <fct> <dbl> <fct>
# 1 1 12 a 145 e
# 2 2 13 b 674 p
然后使用Reduce
加入数据框:
Reduce(function(x, y) left_join(x, y, by = c("A", "B", "C")),
merged_list)
# A B C E.x J.x E.y J.y
# <dbl> <dbl> <fct> <dbl> <fct> <dbl> <fct>
# 1 1 12 a 112 t 145 e
# 2 2 13 b 546 v 674 p
# 3 3 14 c 287 s NA NA
答案 1 :(得分:1)
这几天并不酷,但是Base R的reshape
确实为此而发光,因为它处理不相等的组大小并一次性标记所有内容。您需要先添加一个time
变量来标记每个组:
merged <- merge(df1, cbind(df2, time=ave(df2$A, df2$A, FUN=seq_along)), by="A")
reshape(merged, idvar=names(df1), direction="wide", sep="_")
# A B C E_1 J_1 E_2 J_2
#1 1 12 a 112 t 145 e
#3 2 13 b 546 v 674 p
#5 3 14 c 287 s NA <NA>
它实际上适合dplyr管道,还不错:
df2 %>%
group_by(A) %>%
mutate(time=row_number()) %>%
inner_join(df1,.,by="A") %>%
reshape(idvar=names(df1), direction="wide", sep="_")
答案 2 :(得分:0)
使用data.table
,您可以按行拆分具有相同(E, J)
值的(A, B, C)
行的每组,并将cbind
列出在一起。这里.I
是行号,.N
是组中的行数,.SD
是行组。
这仅在所有组中重复行数相同(只有1行的组除外)时有效
library(data.table)
setDT(merged)
merged[, if(.N > 1) do.call(cbind, split(.SD, .I))
, by = .(A, B, C)]
# A B C 1.E 1.J 2.E 2.J
# 1: 1 12 a 112 t 145 e
# 2: 2 13 b 546 v 674 p
答案 3 :(得分:0)
就像这样,也适用于较大的数据集
df1 <- data.frame(A = c(1:5),
B = c(12, 13, 14, 15, 16),
C = c("a", "b", "c", "d", "e"))
df2 <- data.frame(A = c(1,1,2,2,3),
E = c(112, 145, 546, 674, 287),
J = c("t", "e", "v", "p", "s"))
df3 <- merge(df1, df2, by=c("A"))
df4 <- data.frame()
for (j in 1:(nrow(df3)-1))
for (k in (j+1):nrow(df3))
for (i in 2:ncol(df3))
if(df3[j,1] == df3[k,1] && all(df3[j,i:ncol(df3)]!=df3[k,i:ncol(df3)])){
if(nrow(df4) == 0)
df4 <- data.frame(c(df3[j,],df3[k,i:ncol(df3)]))
else
df4 <- rbind(df4,c(df3[j,],df3[k,i:ncol(df3)]))
break
}