web-dev-qa-db-fra.com

Fusion de plus de 2 trames de données dans R par noms de domaine

Je collecte des données à partir de 4 df et j'aimerais les fusionner par noms de domaine. Je cherche un moyen efficace de le faire. Il s'agit d'une version simplifiée des données dont je dispose.

df1           <- data.frame(N= sample(seq(9, 27, 0.5), 40, replace= T),
                            P= sample(seq(0.3, 4, 0.1), 40, replace= T),
                            C= sample(seq(400, 500, 1), 40, replace= T))
df2           <- data.frame(Origin= sample(c("A", "B", "C", "D", "E"), 40,
                                           replace= T),
                            foo1= sample(c(T, F), 40, replace= T),
                            X= sample(seq(145600, 148300, 100), 40, replace= T),
                            Y= sample(seq(349800, 398600, 100), 40, replace= T))
df3           <- matrix(sample(seq(0, 1, 0.01), 40), 40, 100)
df4           <- matrix(sample(seq(0, 1, 0.01), 40), 40, 100)
rownames(df1) <- paste("P", sprintf("%02d", c(1:40)), sep= "")
rownames(df2) <- rownames(df1)
rownames(df3) <- rownames(df1)
rownames(df4) <- rownames(df1)

Voici ce que je ferais normalement:

# merge df1 and df2
dat           <- merge(df1, df2, by= "row.names", all.x= F, all.y= F) #merge
rownames(dat) <- dat$Row.names #reset rownames
dat$Row.names <- NULL  #remove added rownames col

# merge dat and df3
dat           <- merge(dat, df3, by= "row.names", all.x= F, all.y= F) #merge
rownames(dat) <- dat$Row.names #reset rownames
dat$Row.names <- NULL  #remove added rownames col

# merge dat and df4
dat           <- merge(dat, df4, by= "row.names", all.x= F, all.y= F) #merge
rownames(dat) <- dat$Row.names #reset rownames
dat$Row.names <- NULL #remove added rownames col

Comme vous pouvez le voir, cela nécessite beaucoup de code. Ma question est de savoir si le même résultat peut être obtenu avec des moyens plus simples. J'ai essayé (sans succès): MISE À JOUR: cela fonctionne maintenant!

MyMerge       <- function(x, y){
  df            <- merge(x, y, by= "row.names", all.x= F, all.y= F)
  rownames(df)  <- df$Row.names
  df$Row.names  <- NULL
  return(df)
}
dat           <- Reduce(MyMerge, list(df1, df2, df3, df4))

Merci d'avance pour toute suggestion

32
HDR

Trois lignes de code vous donneront exactement le même résultat:

dat2 <- cbind(df1, df2, df3, df4)
colnames(dat2)[-(1:7)] <- paste(paste('V', rep(1:100, 2),sep = ''),
                            rep(c('x', 'y'), each = 100), sep = c('.'))
all.equal(dat,dat2)    

Ah je vois, maintenant je comprends pourquoi tu ressens autant de douleur. L'utilisation de l'ancienne boucle for fait sûrement l'affaire. Il existe peut-être des solutions encore plus intelligentes

rn <- rownames(df1)
l <- list(df1, df2, df3, df4)
dat <- l[[1]]
for(i in 2:length(l)) {
  dat <- merge(dat, l[[i]],  by= "row.names", all.x= F, all.y= F) [,-1]
  rownames(dat) <- rn
}
6
Edwin

join_all de plyr fera probablement ce que vous voulez. Mais ils doivent tous être des blocs de données et les noms de domaine sont ajoutés sous forme de colonne

require(plyr)

df3 <- data.frame(df3)
df4 <- data.frame(df4)

df1$rn <- rownames(df1)
df2$rn <- rownames(df2)
df3$rn <- rownames(df3)
df4$rn <- rownames(df4)

df <- join_all(list(df1,df2,df3,df4), by = 'rn', type = 'full')

L'argument type devrait aider même si les noms de domaine varient et ne correspondent pas. Si vous ne voulez pas les noms de famille:

df$rn <- NULL
41
Anto

En éditant votre fonction, j'ai trouvé la fonction qui vous permet de fusionner plus de blocs de données par une clé de colonne spécifique (nom de la colonne). La trame de données résultante comprend toutes les variables des trames de données fusionnées (si vous souhaitez conserver uniquement les variables communes (à l'exclusion de NA, utilisez: all.x= FALSE, all.y= FALSE)

MyMerge <- function(x, y){
  df <- merge(x, y, by= "name of the common column", all.x= TRUE, all.y= TRUE)
  return(df)
}
new.df <- Reduce(MyMerge, list(df1, df2, df3, df4))
13
Roxana Adam

Je cherchais la même fonction. Après avoir essayé quelques-unes des options ici et d'autres ailleurs. Le plus simple pour moi a été:

cbind.data.frame (df1, df2, df3, df4 ....)

7
Jorge