2015-12-14 28 views
5

Tôi muốn nối thêm một khung dữ liệu vào khung dữ liệu khác (khung chính). Vấn đề là chỉ tập hợp các cột của họ là phổ biến. Ngoài ra, thứ tự các cột của chúng có thể khác nhau.Nối khung dữ liệu vào khung dữ liệu chính nếu một số cột là phổ biến

Thạc sĩ 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 

Dự kiến ​​kết quả:

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 

Là lại bất kỳ cách thông minh để làm điều này? This là một câu hỏi tương tự nhưng thiết lập khác nhau.

Trả lời

6

Kiểm tra chức năng bind_rows trong gói dplyr. Nó sẽ làm một số điều tốt đẹp cho bạn theo mặc định, chẳng hạn như điền vào các cột tồn tại trong một data.frame nhưng không phải là khác với NA s thay vì chỉ thất bại. Dưới đây là ví dụ:

# 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 

Để giải quyết vấn đề trong câu hỏi của bạn, trước hết bạn muốn chọn các cột trong chủ của mình data.frame. Nếu a là trang chính data.frameb chứa dữ liệu bạn muốn thêm, bạn có thể sử dụng chức năng select từ dplyr để nhận các cột bạn cần trước.

# 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

thử điều này:

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

tùy chọn khác là sử dụng rbind.fill từ gói plyr

mang trong dữ liệu mẫu của bạn

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) 

dữ liệu ràng buộc

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

Nếu bạn đang sử dụng 'dplyr', tại sao không chỉ sử dụng' bind_rows() '? – ialm

+1

@ialm Đọc kỹ hơn, câu trả lời này * không * sử dụng bất kỳ chức năng 'dplyr' nào (nó chỉ tải gói). Cần lưu ý rằng việc tải 'plyr' * sau khi tải' dplyr' sẽ che dấu 'dplyr :: summaryize' và' dplyr :: mutate' bằng các phiên bản 'plyr' và không được khuyến nghị. – Gregor

+1

@Gregor Vâng, tôi thấy điều đó ngay bây giờ. Và vì lý do bạn đánh dấu trong bình luận của bạn, có một cảnh báo được đưa ra nếu bạn tải 'plyr' sau' dplyr', và tôi tin Hadley khuyên bạn nên tải 'plyr' trước' dplyr' nếu bạn cần sử dụng cả hai gói. – ialm

2

dplyr - và plyr giải pháp dựa trên đăng ở đây là rất tự nhiên cho nhiệm vụ này sử dụng bind_rowsrbind.fill, tương ứng, mặc dù nó cũng có thể là một lót trong cơ sở R. Về cơ bản tôi sẽ lặp qua tên của khung dữ liệu, lấy cột tương ứng của khung dữ liệu thứ hai nếu nó có hoặc trả về tất cả các giá trị 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 
Các vấn đề liên quan