2013-04-10 31 views
24

Tôi muốn tổng hợp một cột trong một khung dữ liệu theo hai biến nhóm và phân tách các giá trị riêng lẻ bằng dấu phẩy.Thu gọn/ghép/gộp một cột thành một chuỗi được phân tách bằng dấu phẩy trong mỗi nhóm

Dưới đây là một số dữ liệu:

data <- data.frame(A = c(rep(111, 3), rep(222, 3)), B = rep(1:2, 3), C = c(5:10)) 
data 
#  A B C 
# 1 111 1 5 
# 2 111 2 6 
# 3 111 1 7 
# 4 222 2 8 
# 5 222 1 9 
# 6 222 2 10  

"A" và "B" được nhóm các biến, và "C" là biến mà tôi muốn sụp đổ thành một dấu phẩy tách character chuỗi. Tôi đã thử:

library(plyr) 
ddply(data, .(A,B), summarise, test = list(C)) 

    A B test 
1 111 1 5, 7 
2 111 2  6 
3 222 1  9 
4 222 2 8, 10 

nhưng khi tôi đã cố gắng để chuyển đổi cột thử nghiệm để character nó trở nên như thế này:

ddply(data, .(A,B), summarise, test = as.character(list(C))) 
#  A B  test 
# 1 111 1 c(5, 7) 
# 2 111 2  6 
# 3 222 1  9 
# 4 222 2 c(8, 10) 

Làm thế nào tôi có thể giữ định dạng character và tách chúng bằng dấu phẩy? Ví dụ: hàng 1 chỉ nên là "5,7" và không phải là c (5,7).

Trả lời

28

plyr Hãy thử sử dụng toString:

# plyr 
library(plyr) 
ddply(data, .(A,B), summarize, C = toString(C)) 

Dưới đây là một số lựa chọn thay thế bổ sung cũng sử dụng toString:

data.table

# alternative using data.table 
library(data.table) 
as.data.table(data)[, toString(C), by = list(A, B)] 

tổng này không sử dụng gói:

# alternative using aggregate from the stats package in the core of R 
aggregate(C ~., data, toString) 

sqldf

Và đây là một sự thay thế bằng cách sử dụng chức năng SQL group_concat sử dụng sqldf package:

library(sqldf) 
sqldf("select A, B, group_concat(C) C from data group by A, B", method = "raw") 

dplyr Một dplyr thay thế:

library(dplyr) 
data %>% 
    group_by(A, B) %>% 
    summarise(test = toString(C)) %>% 
    ungroup() 
9

Thay đổi nơi bạn đặt as.character:

> out <- ddply(data, .(A, B), summarise, test = list(as.character(C))) 
> str(out) 
'data.frame': 4 obs. of 3 variables: 
$ A : num 111 111 222 222 
$ B : int 1 2 1 2 
$ test:List of 4 
    ..$ : chr "5" "7" 
    ..$ : chr "6" 
    ..$ : chr "9" 
    ..$ : chr "8" "10" 
> out 
    A B test 
1 111 1 5, 7 
2 111 2  6 
3 222 1  9 
4 222 2 8, 10 

Lưu ý, tuy nhiên, mỗi mục vẫn thực sự là một nhân vật riêng biệt, không phải là một chuỗi ký tự duy nhất. Đó là, đây không phải là một chuỗi thực tế trông giống như "5, 7", mà đúng hơn là hai ký tự "5" và "7", R sẽ hiển thị bằng dấu phẩy giữa chúng.

Hãy so sánh với những điều sau:

> out2 <- ddply(data, .(A, B), summarise, test = paste(C, collapse = ", ")) 
> str(out2) 
'data.frame': 4 obs. of 3 variables: 
$ A : num 111 111 222 222 
$ B : int 1 2 1 2 
$ test: chr "5, 7" "6" "9" "8, 10" 
> out 
    A B test 
1 111 1 5, 7 
2 111 2  6 
3 222 1  9 
4 222 2 8, 10 

Giải pháp so sánh trong cơ sở R là, tất nhiên, aggregate:

> A1 <- aggregate(C ~ A + B, data, function(x) c(as.character(x))) 
> str(A1) 
'data.frame': 4 obs. of 3 variables: 
$ A: num 111 222 111 222 
$ B: int 1 1 2 2 
$ C:List of 4 
    ..$ 0: chr "5" "7" 
    ..$ 1: chr "9" 
    ..$ 2: chr "6" 
    ..$ 3: chr "8" "10" 
> A2 <- aggregate(C ~ A + B, data, paste, collapse = ", ") 
> str(A2) 
'data.frame': 4 obs. of 3 variables: 
$ A: num 111 222 111 222 
$ B: int 1 1 2 2 
$ C: chr "5, 7" "9" "6" "8, 10" 
Các vấn đề liên quan