получить значения из фрейма данных в другой - PullRequest
1 голос
/ 23 мая 2011

Я новичок в программировании на R и только начал изучать его, и мне нужно, чтобы вы помогли мне с этим вопросом, пожалуйста.

У меня есть 2 кадра данных:

the first(df1):

    V1 V2
    A  A 
    A  B 
    A  C 
    B  A 
    B  B 
    B  C 

etc

второй (df2):

V1  Va   Vb
A   12   23
B   15   53
C   321  543
D   54   325
etc..

Используйте этот код для генерации данных примера.

df1 <- data.frame(
  V1 = rep(LETTERS[1:2], each = 3L),
  V2 = rep.int(LETTERS[1:3], 2L)
)
dfr2 <- data.frame(
  Va = c(12, 15, 312, 54),
  Vb = c(23, 53, 543, 325)
)

Мне нужно взять Va и Vb из df2 и поместить их в df1 на основе V1 и V2 из df1.

так что я хочу этот вывод:

DF3:

V1   V2  Va1  Vb1 Va2 Vb2
A    A   12    23  12  23
A    B   12    23  15  23
A    C   12    23  321 543
B    A   15    23  12   23
B    B   15    23  15   23
B    C   15    23  321  543

надеюсь, что это можно сделать в R без дюжины циклов for: S.

Ответы [ 3 ]

4 голосов
/ 23 мая 2011

Вы можете использовать merge() дважды, чтобы получить то, что вы хотите. По умолчанию merge ищет общие имена столбцов для присоединения. Во втором слиянии мы укажем столбец, с которым мы хотим слить:

df1 <- data.frame(V1 = c('A', 'A', 'A', 'B', 'B', 'B'), V2 = c('A', 'B', 'C', 'A', 'B', 'C'))
df2 <- data.frame(V1 = c('A', 'B', 'C', 'D'), Va = c(12, 15, 321, 54), Vb = c(23, 53, 543, 325))

merge(merge(df1, df2), df2, by.x = "V2", by.y = "V1", suffixes = c("1", "2"))
1 голос
/ 29 апреля 2016

Я думаю, что в пакете dplyr Хэдли Уикхэма есть несколько отличных инструментов для объединения фреймов данных.Это другой способ добраться до того же места.

df1 <- data.frame(
  V1 = rep(LETTERS[1:2], each = 3L),
  V2 = rep.int(LETTERS[1:3], 2L)
)
dfr2 <- data.frame(
  V1 = LETTERS[1:4],
  Va = c(12, 15, 312, 54),
  Vb = c(23, 53, 543, 325)
)

##necessary libraries
library(magrittr, dplyr)

Теперь, используя функции left_join() и rename() из пакета dplyr и оператора pipe из пакета magrittr,Я думаю, что вы можете сохранить много нажатий клавиш.

df3 <- df1 %>% #pipe operator (%>%) is from magrittr package
  dplyr::left_join(dfr2, c('V1'="V1")) %>% #merge once
  dplyr::rename(Va1 = Va, Vb1 = Vb) %>%  #rename columns
  dplyr::left_join(dfr2, c('V2'="V1")) %>% #merge on different column
  dplyr::rename(Va2 = Va, Vb2 = Vb) #rename again

Это также можно сделать одним объединением вместо двух, но мне нравится видеть, что происходит на каждом шаге.

> print(df3)
  V1 V2 Va1 Vb1 Va2 Vb2
1  A  A  12  23  12  23
2  A  B  12  23  15  53
3  A  C  12  23 312 543
4  B  A  15  53  12  23
5  B  B  15  53  15  53
6  B  C  15  53 312 543
1 голос
/ 23 мая 2011

Для этого вы можете использовать силу match (), если имена в df1 $ V1 уникальны:

#some data
df1 <- data.frame(
  V1 = rep(c("A","B"),each=3),
  V2 = rep(LETTERS[1:3],2)  
)
df2 <- data.frame(V1=LETTERS[1:3],Va=1:3,Vb=3:1)

out <- cbind(df1,
  df2[match(df1$V1,df2$V1),-1],
  df2[match(df1$V2,df2$V1),-1]
)
names(out)[3:6] <- c("Va1","Vb1","Va2","Vb2")
rownames(out) <- 1:nrow(out)

Дает

> out
    V1 V2 Va1 Vb1 Va2 Vb2
1    A  A   1   3   1   3
2    A  B   1   3   2   2
3    A  C   1   3   3   1
4    B  A   2   2   1   3
5    B  B   2   2   2   2
6    B  C   2   2   3   1

Вам придется переименоватьстолбцы вручную, так как вы получите несколько столбцов с одинаковым именем.Хотя это технически возможно в фрейме данных, это может вызвать проблемы позже.Вы можете автоматизировать это, используя что-то вроде:

names(out) <- 
    c("V1","V2",
      sapply(names(df2)[2:3],paste,1:2,sep="")
    )

РЕДАКТИРОВАТЬ: для больших фреймов данных преобразование в матрицы имеет еще одно огромное отличие.Нужно обратить внимание на внутренние изменения в типе для различных переменных.Ускорение связано с тем, что cbind и merge занимают много времени для определения правильных типов для каждой переменной.

Со следующими данными и функциями:

n <- 1e5
df1 <- data.frame(V1 = rep(LETTERS,each=n),V2 = rep(LETTERS,n),
        stringsAsFactors=FALSE)
df2 <- data.frame(V1=LETTERS,Va=1:26,Vb=26:1,stringsAsFactors=FALSE)

fast_JM <- function(df1,df2){
  out <- cbind(
    as.matrix(df2[,-1])[match(df1$V1,df2$V1),],
    as.matrix(df2[,-1])[match(df1$V2,df2$V1),]
  )
  out <- as.data.frame(out)
  names(out) <- sapply(names(df2)[2:3],paste,1:2,sep="")
  out$V1 <- df1$V1
  out$V2 <- df1$V2
  out
}

slow_JM <- function(df1,df2){
  out <- cbind(df1,
    df2[match(df1$V1,df2$V1),-1],
    df2[match(df1$V2,df2$V1),-1]
  )
  names(out)[3:6] <- c("Va1","Vb1","Va2","Vb2")
  out
}


double_merge <- function(df1,df2){
  merge(merge(df1, df2), df2, by.x = "V2", by.y = "V1", suffixes = c("1", "2"))

}

эталоном становится:

require(rbenchmark)
benchmark(fast_JM(df1,df2),slow_JM(df1,df2),double_merge(df1,df2),
      replications=1,columns=c("test","elapsed","relative"),order="relative")

                    test elapsed relative
1      fast_JM(df1, df2)    0.89  1.00000
2      slow_JM(df1, df2)   12.54 14.08989
3 double_merge(df1, df2)   42.50 47.75281

Таким образом, ускорение более чем в 40 раз по сравнениюдо двойного слияния и более чем в 10 раз по сравнению с использованием фреймов данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...