J'ai une liste de nombreux data.frames que je veux fusionner. Le problème ici est que chaque data.frame diffère en termes de nombre de lignes et de colonnes, mais ils partagent tous les variables clés (que j'ai appelées "var1"
et "var2"
dans le code ci-dessous). Si les data.frames étaient identiques en termes de colonnes, je pourrais simplement rbind
, pour lequel ryrind.fill de plyr ferait le travail, mais ce n'est pas le cas avec ces données.
Parce que la merge
commande ne fonctionne que sur 2 data.frames, je me suis tourné vers Internet pour des idées. J'ai obtenu celui-ci d' ici , qui fonctionnait parfaitement dans R 2.7.2, ce que j'avais à l'époque:
merge.rec <- function(.list, ...){
if(length(.list)==1) return(.list[[1]])
Recall(c(list(merge(.list[[1]], .list[[2]], ...)), .list[-(1:2)]), ...)
}
Et j'appellerais la fonction comme ceci:
df <- merge.rec(my.list, by.x = c("var1", "var2"),
by.y = c("var1", "var2"), all = T, suffixes=c("", ""))
Mais dans toute version R après 2.7.2, y compris 2.11 et 2.12, ce code échoue avec l'erreur suivante:
Error in match.names(clabs, names(xi)) :
names do not match previous names
(Par ailleurs, je vois d'autres références à cette erreur ailleurs sans résolution).
Est-ce qu'il y a un moyen de résoudre ceci?
map_dfr()
oumap_dfc()
dfs = [df1, df2, df3]
alorsreduce(pandas.merge, dfs)
.Réduire rend cela assez simple:
Voici un exemple complet utilisant des données fictives:
Et voici un exemple utilisant ces données pour répliquer
my.list
:Remarque: il semble que ce soit un bogue
merge
. Le problème est qu'il n'y a aucune vérification que l'ajout des suffixes (pour gérer les noms non correspondants qui se chevauchent) les rend réellement uniques. À un certain moment, il utilise[.data.frame
ce qui faitmake.unique
les noms, provoquant l'rbind
échec de.Le moyen le plus simple de corriger est de ne pas laisser le champ renommer les champs en double (dont il y en a beaucoup ici) jusqu'à
merge
. Par exemple:Le
merge
/Reduce
fonctionnera alors correctement.la source
empty <- data.frame(x=numeric(0),a=numeric(0); L3 <- c(empty,empty,list.of.data.frames,empty,empty,empty)
et il s'est passé des trucs bizarres que je n'ai pas encore compris.Vous pouvez le faire en utilisant
merge_all
dans lereshape
package. Vous pouvez passer des paramètres à l'merge
aide de l'...
argumentVoici une excellente ressource sur différentes méthodes de fusion de trames de données .
la source
Vous pouvez utiliser la récursivité pour ce faire. Je n'ai pas vérifié les éléments suivants, mais cela devrait vous donner la bonne idée:
la source
Je vais réutiliser l'exemple de données de @PaulRougieux
Voici une solution courte et douce en utilisant
purrr
ettidyr
la source
La fonction
eat
de mon package safejoin a une telle fonctionnalité, si vous lui donnez une liste de data.frames en tant que deuxième entrée, elles les rejoindront récursivement à la première entrée.Emprunter et étendre les données de la réponse acceptée:
Nous n'avons pas à prendre toutes les colonnes, nous pouvons utiliser certains assistants de tidyselect et choisir (comme nous partons de
.x
toutes les.x
colonnes sont conservées):ou supprimez ceux spécifiques:
Si la liste est nommée, les noms seront utilisés comme préfixes:
S'il y a des conflits de colonnes, l'
.conflict
argument vous permet de le résoudre, par exemple en prenant le premier / second, en les ajoutant, en les fusionnant ou en les imbriquant.garder en premier:
garder en dernier:
ajouter:
se fondre:
nid:
NA
les valeurs peuvent être remplacées en utilisant l'.fill
argument.Par défaut, c'est une amélioration,
left_join
mais toutes les jointures dplyr sont prises en charge via l'.mode
argument, les jointures floues sont également prises en charge via l'match_fun
argument (il est enroulé autour du packagefuzzyjoin
) ou en donnant une formule telle que~ X("var1") > Y("var2") & X("var3") < Y("var4")
l'by
argument.la source
J'avais une liste de trames de données sans colonne d'ID commune.
Il me manquait des données sur de nombreux DFS. Il y avait des valeurs nulles. Les trames de données ont été produites à l'aide de la fonction de table. La fonction Réduire, Fusionner, rbind, rbind.fill et leurs semblables ne pouvaient pas m'aider à atteindre mon objectif. Mon objectif était de produire une trame de données fusionnée compréhensible, sans rapport avec les données manquantes et la colonne d'identification commune.
Par conséquent, j'ai fait la fonction suivante. Peut-être que cette fonction peut aider quelqu'un.
il suit la fonction
Exécuter l'exemple
la source
Lorsque vous avez une liste de dfs et qu'une colonne contient l '"ID", mais dans certaines listes, certains ID sont manquants, vous pouvez utiliser cette version de Reduce / Merge afin de joindre plusieurs Dfs d'ID de ligne ou d'étiquettes manquantes:
la source
Voici un wrapper générique qui peut être utilisé pour convertir une fonction binaire en fonction multi-paramètres. L'avantage de cette solution est qu'elle est très générique et peut être appliquée à toutes les fonctions binaires. Vous n'avez qu'à le faire une fois et vous pouvez l'appliquer n'importe où.
Pour faire une démonstration de l'idée, j'utilise une récursivité simple à implémenter. Il peut bien sûr être implémenté de manière plus élégante qui bénéficie du bon support de R pour le paradigme fonctionnel.
Ensuite, vous pouvez simplement envelopper toutes les fonctions binaires avec lui et appeler avec les paramètres de position (généralement data.frames) dans les premières parenthèses et les paramètres nommés dans les secondes parenthèses (comme
by =
ousuffix =
). Si aucun paramètre nommé, laissez les deuxièmes parenthèses vides.la source