2015-12-14 44 views
5

Chcę dołączyć jedną ramkę danych do drugiej (główna). Problem polega na tym, że tylko podzbiór ich kolumn jest wspólny. Kolejność ich kolumn może być inna.Dołączanie ramki danych do głównej ramki danych, jeśli niektóre kolumny są wspólne

Mistrz dataframe:

a b c 
r1 1 2 -2 
r2 2 4 -4 
r3 3 6 -6 
r4 4 8 -8 

New dataframe:

 d a c 
r1 -120 10 -20 
r2 -140 20 -40 

Oczekiwany wynik:

a b c 
r1 1 2 -2 
r2 2 4 -4 
r3 3 6 -6 
r4 4 8 -8 
r5 10 NaN -20 
r6 20 NaN -40 

Czy Czy jest jakiś inteligentny sposób robienia tego? This to podobne pytanie, ale konfiguracja jest inna.

Odpowiedz

6

Zapoznaj się z funkcją bind_rows w pakiecie dplyr. Domyślnie zrobi to dla ciebie kilka fajnych rzeczy, takich jak wypełnianie kolumn, które istnieją w jednym data.frame, ale nie w innych z NA s zamiast po prostu nie. Oto przykład:

# Use the dplyr package for binding rows and for selecting columns 
library(dplyr) 

# Generate some example data 
a <- data.frame(a = rnorm(10), b = rnorm(10)) 
b <- data.frame(a = rnorm(5), c = rnorm(5)) 

# Stack data frames 
bind_rows(a, b) 

Source: local data frame [15 x 3] 

      a   b   c 
1 2.2891895 0.1940835   NA 
2 0.7620825 -0.2441634   NA 
3 1.8289665 1.5280338   NA 
4 -0.9851729 -0.7187585   NA 
5 1.5829853 1.6609695   NA 
6 0.9231296 1.8052112   NA 
7 -0.58-0.6928449   NA 
8 0.2033514 -0.6673596   NA 
9 -0.8576628 0.5163021   NA 
10 0.6296633 -1.2445280   NA 
11 2.1693068   NA -0.2556584 
12 -0.1048966   NA -0.3132198 
13 0.2673514   NA -1.1181995 
14 1.0937759   NA -2.5750115 
15 -0.8147180   NA -1.5525338 

Aby rozwiązać ten problem w swoim pytaniu, że chcesz wybrać dla kolumn w swojego mistrza data.frame pierwszy. Jeśli a jest wzorcem data.frame, a b zawiera dane, które chcesz dodać, możesz użyć funkcji select z dplyr, aby uzyskać kolumny, których potrzebujesz jako pierwsze.

# Select all columns in b with the same names as in master data, a 
# Use select_() instead of select() to do standard evaluation. 
b <- select_(b, names(a)) 

# Combine 
bind_rows(a, b) 

Source: local data frame [15 x 2] 

      a   b 
1 2.2891895 0.1940835 
2 0.7620825 -0.2441634 
3 1.8289665 1.5280338 
4 -0.9851729 -0.7187585 
5 1.5829853 1.6609695 
6 0.9231296 1.8052112 
7 -0.58-0.6928449 
8 0.2033514 -0.6673596 
9 -0.8576628 0.5163021 
10 0.6296633 -1.2445280 
11 2.1693068   NA 
12 -0.1048966   NA 
13 0.2673514   NA 
14 1.0937759   NA 
15 -0.8147180   NA 
2

spróbuj tego:

library(plyr) # thanks to comment @ialm 
df <- data.frame(a=1:4,b=seq(2,8,2),c=seq(-2,-8,-2)) 
new <- data.frame(d=c(-120,-140),a=c(10,20),c=c(-20,40)) 

# we use %in% to pull the columns that are the same in the master 
# then we use rbind.fill to put in this dataframe below the master 
# filling any missing data with NA values 
res <- rbind.fill(df,new[,colnames(new) %in% colnames(df)]) 

> res 
    a b c 
1 1 2 -2 
2 2 4 -4 
3 3 6 -6 
4 4 8 -8 
5 10 NA -20 
6 20 NA 40 
1

Inną opcją jest użycie rbind.fill z pakietu plyr

przynieść danych przykładowych

toread <- " 
a b c 
1 2 -2 
2 4 -4 
3 6 -6 
4 8 -8" 
master <- read.table(textConnection(toread), header = TRUE) 
toread <- " 
d a c 
-120 10 -20 
-140 20 -40" 
to.append <- read.table(textConnection(toread), header = TRUE) 

dane Bind

library(plyr) 
rbind.fill(master, to.append) 
+1

Jeśli używasz 'dplyr', dlaczego nie użyć po prostu' bind_rows() '? – ialm

+1

@ialm Dzięki dokładniejszemu czytaniu ta odpowiedź * nie * używa żadnych funkcji 'dplyr' (po prostu ładuje pakiet). Warto zauważyć, że ładowanie 'plyr' * po * ładowaniu' dplyr' będzie maskować 'dplyr :: summary' i' dplyr :: mutate' z wersjami 'plyr' i nie jest zalecane. – Gregor

+1

@Gregor Tak, teraz to widzę. I z powodów, które podkreślasz w swoim komentarzu, pojawi się ostrzeżenie, jeśli załadujesz 'plyr' po' dplyr' i sądzę, że Hadley zaleca ładowanie 'plyr' przed' dplyr', jeśli będziesz potrzebował użyć obu pakietów. – ialm

2

Zamieszczone tutaj rozwiązania są bardzo naturalne dla tego zadania, używając odpowiednio bind_rows i rbind.fill, chociaż możliwe jest również jako jednoelement w bazie R. Zasadniczo przeszukuję nazwy pierwszych ramka danych, przechwytuje odpowiednią kolumnę drugiej ramki danych, jeśli jest tam lub w inny sposób zwraca wszystkie wartości NaN.

rbind(A, sapply(names(A), function(x) if (x %in% names(B)) B[,x] else rep(NaN, nrow(B)))) 
#  a b c 
# r1 1 2 -2 
# r2 2 4 -4 
# r3 3 6 -6 
# r4 4 8 -8 
# 5 10 NaN -20 
# 6 20 NaN -40