2016-07-21 19 views
7

tôi có một dataframe trông như thế nàyCONCATENATE chuỗi theo nhóm với dplyr

> data <- data.frame(foo=c(1, 1, 2, 3, 3, 3), bar=c('a', 'b', 'a', 'b', 'c', 'd')) 
> data 
    foo bar 
1 1 a 
2 1 b 
3 2 a 
4 3 b 
5 3 c 
6 3 d 

Tôi muốn tạo ra một bars_by_foo cột mới đó là nối các giá trị của thanh bằng foo. Vì vậy, các dữ liệu mới sẽ trông như thế này:

foo bar bars_by_foo 
1 1 a   ab 
2 1 b   ab 
3 2 a   a 
4 3 b   bcd 
5 3 c   bcd 
6 3 d   bcd 

Tôi đã hy vọng rằng những điều sau đây sẽ làm việc:

p <- function(v) { 
    Reduce(f=paste, x = v) 
} 
data %>% 
    group_by(foo) %>% 
    mutate(bars_by_foo=p(bar)) 

Nhưng mã mà mang lại cho tôi một lỗi

Error: incompatible types, expecting a character vector.

Tôi đang làm gì sai?

Trả lời

21

Bạn chỉ có thể làm

data %>% 
    group_by(foo) %>% 
    mutate(bars_by_foo = paste0(bar, collapse = "")) 

Nếu không có bất kỳ chức năng helper

+0

Oh sự sụp đổ = "" là sự khác biệt! Nếu không có nó không hoạt động, đó là lý do tại sao tôi đã viết chức năng trợ giúp. – crf

+0

Cũng lưu ý rằng sự sụp đổ có thể là bất cứ điều gì nó, chỉ có thể không được NULL. Bạn có thể sử dụng collapse = "" hoặc collapse = "," nếu bạn muốn. –

1

Bạn có thể thử này:

agg <- aggregate(bar~foo, data = data, paste0, collapse="") 
df <- merge(data, agg, by = "foo", all = T) 
colnames(df) <- c(colnames(data), "bars_by_foo") # optional 


    # foo bar bars_by_foo 
# 1 1  a ab 
# 2 1  b ab 
# 3 2  a  a 
# 4 3  b bcd 
# 5 3  c bcd 
# 6 3  d bcd 
2

Dường như có một chút của một vấn đề với mutate chức năng - Tôi đã phát hiện ra rằng đó là một phương pháp tốt hơn để làm việc với summarise khi bạn nhóm dữ liệu trong dplyr (đó là không có cách nào một quy tắc cứng và nhanh chóng mặc dù).

paste chức năng cũng giới thiệu khoảng trắng vào kết quả để thiết lập sep = 0 hoặc sử dụng chỉ sử dụng paste0.

Đây là mã của tôi:

p <- function(v) { 
    Reduce(f=paste0, x = v) 
} 

data %>% 
    group_by(foo) %>% 
    summarise(bars_by_foo = p(as.character(bar))) %>% 
    merge(., data, by = 'foo') %>% 
    select(foo, bar, bars_by_foo) 

Hệ quả là ..

foo bar bars_by_foo 
1 1 a   ab 
2 1 b   ab 
3 2 a   a 
4 3 b   bcd 
5 3 c   bcd 
6 3 d   bcd 
+0

Việc sử dụng Tóm tắt thực sự đẩy mạnh hoạt động tương tự của tôi. Tôi đã không làm bất kỳ nhóm nào, chỉ cần nối cột đầy đủ, vì vậy không nghĩ về nó. Cuộc gọi tốt. Cắt paste0 của tôi xuống từ 5 phút xuống còn ~ 3 giây. –

0

Chức năng của bạn hoạt động nếu bạn đảm bảo thanh đó là tất cả ký tự và không cấp độ của một yếu tố.

data <- data.frame(foo=c(1, 1, 2, 3, 3, 3), bar=c('a', 'b', 'a', 'b', 'c', 'd'), 
stringsAsFactors = FALSE) 

library("dplyr") 

p <- function(v) { 
    Reduce(f=paste, x = v) 
} 

data %>% 
    group_by(foo) %>% 
    mutate(bars_by_foo=p(bar)) 


Source: local data frame [6 x 3] 
Groups: foo [3] 

    foo bar bars_by_foo 
    <dbl> <chr>  <chr> 
    1  1  a  a b 
    2  1  b  a b 
    3  2  a  a 
    4  3  b b c d 
    5  3  c b c d 
    6  3  d b c d 
Các vấn đề liên quan