我有一个列表,里面有很多我想合并的数据帧。这里的问题是,每个data.frame的行数和列数不同,但它们都共享关键变量(在下文中我将其称为“var1”和“var2”)。如果data.frames在列方面是相同的,我可以只rbind,对于plyr的rbind。填充可以完成这项工作,但这些数据不是这样的。

因为merge命令只适用于2 data.frames,所以我求助于互联网。我从这里得到了这个,它在R 2.7.2中完美地工作,这是我当时拥有的:

merge.rec <- function(.list, ...){
    if(length(.list)==1) return(.list[[1]])
    Recall(c(list(merge(.list[[1]], .list[[2]], ...)), .list[-(1:2)]), ...)
}

我将这样调用这个函数:

df <- merge.rec(my.list, by.x = c("var1", "var2"), 
                by.y = c("var1", "var2"), all = T, suffixes=c("", ""))

但在2.7.2之后的任何R版本中,包括2.11和2.12,这段代码会出现以下错误:

Error in match.names(clabs, names(xi)) : 
  names do not match previous names

(顺便说一句,我在其他地方看到了这个错误的其他引用,但没有解决方案)。

有办法解决这个问题吗?


当前回答

我有一个没有公共id列的数据框架列表。 我丢失了许多dfs的数据。有Null值。 数据帧是使用表函数生成的。 还原,合并,rbind, rbind。填满,他们的同类不能帮助我达到我的目标。 我的目标是产生一个可理解的合并数据框架,与缺失的数据和公共id列无关。

因此,我做了如下函数。也许这个函数可以帮助到某些人。

##########################################################
####             Dependencies                        #####
##########################################################

# Depends on Base R only

##########################################################
####             Example DF                          #####
##########################################################

# Example df
ex_df           <- cbind(c( seq(1, 10, 1), rep("NA", 0), seq(1,10, 1) ), 
                         c( seq(1, 7, 1),  rep("NA", 3), seq(1, 12, 1) ), 
                         c( seq(1, 3, 1),  rep("NA", 7), seq(1, 5, 1), rep("NA", 5) ))

# Making colnames and rownames
colnames(ex_df) <- 1:dim(ex_df)[2]
rownames(ex_df) <- 1:dim(ex_df)[1]

# Making an unequal list of dfs, 
# without a common id column
list_of_df      <- apply(ex_df=="NA", 2, ( table) )

它遵循函数

##########################################################
####             The function                        #####
##########################################################


# The function to rbind it
rbind_null_df_lists <- function ( list_of_dfs ) {
  length_df     <- do.call(rbind, (lapply( list_of_dfs, function(x) length(x))))
  max_no        <- max(length_df[,1])
  max_df        <- length_df[max(length_df),]
  name_df       <- names(length_df[length_df== max_no,][1])
  names_list    <- names(list_of_dfs[ name_df][[1]])

  df_dfs <- list()
  for (i in 1:max_no ) {

    df_dfs[[i]]            <- do.call(rbind, lapply(1:length(list_of_dfs), function(x) list_of_dfs[[x]][i]))

  }

  df_cbind               <- do.call( cbind, df_dfs )
  rownames( df_cbind )   <- rownames (length_df)
  colnames( df_cbind )   <- names_list

  df_cbind

}

运行示例

##########################################################
####             Running the example                 #####
##########################################################

rbind_null_df_lists ( list_of_df )

其他回答

我将重复使用来自@PaulRougieux的数据示例

x <- data_frame(i = c("a","b","c"), j = 1:3)
y <- data_frame(i = c("b","c","d"), k = 4:6)
z <- data_frame(i = c("c","d","a"), l = 7:9)

这里有一个简短而甜蜜的解决方案,使用purrr和tidyr

library(tidyverse)

 list(x, y, z) %>% 
  map_df(gather, key=key, value=value, -i) %>% 
  spread(key, value)

我有一个没有公共id列的数据框架列表。 我丢失了许多dfs的数据。有Null值。 数据帧是使用表函数生成的。 还原,合并,rbind, rbind。填满,他们的同类不能帮助我达到我的目标。 我的目标是产生一个可理解的合并数据框架,与缺失的数据和公共id列无关。

因此,我做了如下函数。也许这个函数可以帮助到某些人。

##########################################################
####             Dependencies                        #####
##########################################################

# Depends on Base R only

##########################################################
####             Example DF                          #####
##########################################################

# Example df
ex_df           <- cbind(c( seq(1, 10, 1), rep("NA", 0), seq(1,10, 1) ), 
                         c( seq(1, 7, 1),  rep("NA", 3), seq(1, 12, 1) ), 
                         c( seq(1, 3, 1),  rep("NA", 7), seq(1, 5, 1), rep("NA", 5) ))

# Making colnames and rownames
colnames(ex_df) <- 1:dim(ex_df)[2]
rownames(ex_df) <- 1:dim(ex_df)[1]

# Making an unequal list of dfs, 
# without a common id column
list_of_df      <- apply(ex_df=="NA", 2, ( table) )

它遵循函数

##########################################################
####             The function                        #####
##########################################################


# The function to rbind it
rbind_null_df_lists <- function ( list_of_dfs ) {
  length_df     <- do.call(rbind, (lapply( list_of_dfs, function(x) length(x))))
  max_no        <- max(length_df[,1])
  max_df        <- length_df[max(length_df),]
  name_df       <- names(length_df[length_df== max_no,][1])
  names_list    <- names(list_of_dfs[ name_df][[1]])

  df_dfs <- list()
  for (i in 1:max_no ) {

    df_dfs[[i]]            <- do.call(rbind, lapply(1:length(list_of_dfs), function(x) list_of_dfs[[x]][i]))

  }

  df_cbind               <- do.call( cbind, df_dfs )
  rownames( df_cbind )   <- rownames (length_df)
  colnames( df_cbind )   <- names_list

  df_cbind

}

运行示例

##########################################################
####             Running the example                 #####
##########################################################

rbind_null_df_lists ( list_of_df )

当你有一个dfs列表,其中一列包含“ID”,但在某些列表中,一些ID缺失,那么你可以使用这个版本的Reduce / Merge来连接多个缺少行ID或标签的dfs:

Reduce(function(x, y) merge(x=x, y=y, by="V1", all.x=T, all.y=T), list_of_dfs)

你可以在重塑包中使用merge_all。您可以使用…来传递参数进行合并。论点

reshape::merge_all(list_of_dataframes, ...)

这里有一个关于合并数据帧的不同方法的优秀资源。

你可以使用递归来做到这一点。我还没有验证以下内容,但它应该会给你一个正确的想法:

MergeListOfDf = function( data , ... )
{
    if ( length( data ) == 2 ) 
    {
        return( merge( data[[ 1 ]] , data[[ 2 ]] , ... ) )
    }    
    return( merge( MergeListOfDf( data[ -1 ] , ... ) , data[[ 1 ]] , ... ) )
}