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
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
}
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
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))
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 ....)