Подтвердить что ты не робот

Объединение более 2-х кадров данных в R по именам ростов

Я собираю данные из 4 df и хотел бы объединить их по именам ростов. Я ищу эффективный способ сделать это. Это упрощенная версия данных, которые у меня есть.

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)

Это то, что я обычно делал:

# 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

Как вы можете видеть, для этого требуется много кода. Мой вопрос в том, можно ли добиться того же результата с помощью более простых средств. Я пробовал (без успеха): UPDATE: теперь это работает!

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

Заранее благодарим за любые предложения

4b9b3361

Ответ 1

join_all from plyr, вероятно, сделает то, что вы хотите. Но все они должны быть кадры данных, а имена ростов добавляются как столбец

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')
Аргумент

type должен помочь, даже если имена розеток меняются и не совпадают Если вам не нужны имена розеток:

df$rn <- NULL

Ответ 2

Редактирование вашей функции, я придумал функцию, которая позволяет объединить больше кадров данных с помощью конкретного столбца (имя столбца). Приведенный кадр данных включает в себя всю переменную объединенных кадров данных (если вы хотите сохранить только общие переменные (исключая NA, используйте: 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))

Ответ 3

Три строки кода предоставят вам тот же результат:

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)    

А я вижу, теперь я понимаю, почему вы так сильно страдаете. Использование старого цикла for, безусловно, делает трюк. Возможно, есть еще более умные решения.

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
}

Ответ 4

Я искал ту же функцию. Попробовав пару вариантов здесь и других в другом месте. Самый легкий для меня был:

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