加入后多行合一

时间:2018-08-19 21:40:56

标签: r

我必须加入两个数据框。联接工作正常,我唯一的问题是:

有时我在数据集中有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:**

我的原始数据帧具有

  1. 具有1535个观测值的354个项目
  2. 246个项目203个观察结果

它们被第一列id_merge合并。有时我有2个匹配项,有时有3个相同的“ id_merge”值。

4 个答案:

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