2016-07-21 23 views
7

mam dataframe który wygląda takłączenia ciągów autorstwa grupy z 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 

Chciałbym utworzyć nową kolumnę bars_by_foo która jest połączeniem wartości Bar od foo. Tak więc nowe dane powinny wyglądać następująco:

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 

miałem nadzieję, że będzie działać co następuje:

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

Ale ten kod daje mi błąd

Error: incompatible types, expecting a character vector.

Co robię źle?

Odpowiedz

21

Można po prostu zrobić

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

bez żadnych funkcji pomocniczych

+0

Oh the collapse = "" to różnica! Bez tego to nie działa, dlatego napisałem funkcję pomocnika. – crf

+0

Należy również pamiętać, że zwinięcie może być dowolne, po prostu nie może mieć wartości NULL. Możesz użyć collapse = "" lub collapse = "," jeśli chcesz. –

1

Można spróbować to:

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

Wygląda na to, że to trochę problem z funkcją mutate - Odkryłem, że jest to lepsze podejście do pracy z summarise kiedy grupowania danych w dplyr (nie jest to jednak żadna twarda i szybka reguła).

Funkcja paste wprowadza również białe znaki do wyniku, aby ustawić sep = 0 lub użyć po prostu użyć paste0.

Oto mój kod:

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) 

Powstałe w ..

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

Zastosowanie przedstawiono podsumowanie naprawdę przyspieszyło moją podobną operację. Nie robiłem żadnego zgrupowania, tylko łącząc całą kolumnę, więc nie pomyślałem o tym. Dobra decyzja. Wytnij moją paste0 w dół z 5+ minut do ~ 3 sekund. –

0

Twoja funkcja działa, jeśli zapewniają, że bar są wszystkie znaki, a nie poziomy czynnika.

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 
Powiązane problemy