Ich möchte eine Spalte in einem Datenrahmen nach zwei Gruppierungsvariablen aggregieren und die einzelnen Werte durch ein Komma trennen.
Hier sind einige Daten:
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" und "B" sind Gruppierungsvariablen, und "C" ist die Variable, die ich in eine durch Kommas getrennte character
Zeichenfolge reduzieren möchte . Ich habe versucht:
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
Aber als ich versuchte, die Testspalte in eine solche zu konvertieren, sieht character
es so aus:
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)
Wie kann ich das character
Format beibehalten und durch Komma trennen? Zum Beispiel sollte Zeile 1 nur "5,7"
und nicht c (5,7) sein.
Hier ist die
stringr
/tidyverse
Lösung:library(tidyverse) library(stringr) data <- data.frame(A = c(rep(111, 3), rep(222, 3)), B = rep(1:2, 3), C = c(5:10)) data %>% group_by(A, B) %>% summarize(text = str_c(C, collapse = ", ")) # A tibble: 4 x 3 # Groups: A [2] A B test <dbl> <int> <chr> 1 111 1 5, 7 2 111 2 6 3 222 1 9 4 222 2 8, 10
quelle
stringr::str_c
fürpaste
von der Basis R.Ändern Sie, wo Sie setzen
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
Beachten Sie jedoch, dass jedes Element immer noch ein separates Zeichen und keine einzelne Zeichenfolge ist. Das heißt, dies ist keine tatsächliche Zeichenfolge, die wie "5, 7" aussieht, sondern zwei Zeichen, "5" und "7", die R mit einem Komma dazwischen anzeigt.
Vergleichen Sie mit folgendem:
> 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
Die vergleichbare Lösung in Base R ist natürlich
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"
quelle
Hier gibt es eine kleine Verbesserung, um Duplikate zu vermeiden
# 1. Original data set data <- data.frame( A = c(rep(111, 3), rep(222, 3)), B = rep(1:2, 3), C = c(5:10)) # 2. Add duplicate row data <- rbind(data, data.table( A = 111, B = 1, C = 5 )) # 3. Solution with duplicates data %>% group_by(A, B) %>% summarise(test = toString(C)) %>% ungroup() # A B test # <dbl> <dbl> <chr> # 1 111 1 5, 7, 5 # 2 111 2 6 # 3 222 1 9 # 4 222 2 8, 10 # 4. Solution without duplicates data %>% select(A, B, C) %>% unique() %>% group_by(A, B) %>% summarise(test = toString(C)) %>% ungroup() # A B test # <dbl> <dbl> <chr> # 1 111 1 5, 7 # 2 111 2 6 # 3 222 1 9 # 4 222 2 8, 10
Hoffe es kann nützlich sein.
quelle