Połącz dwie lub więcej kolumn w ramce danych w nową kolumnę z nową nazwą

104

Na przykład, jeśli mam to:

n = c(2, 3, 5) 
s = c("aa", "bb", "cc") 
b = c(TRUE, FALSE, TRUE) 
df = data.frame(n, s, b)

  n  s     b
1 2 aa  TRUE
2 3 bb FALSE
3 5 cc  TRUE

Następnie jak połączyć dwie kolumny ni sutworzyć nową kolumnę nazwaną xtak, aby wyglądała tak:

  n  s     b     x
1 2 aa  TRUE  2 aa
2 3 bb FALSE  3 bb
3 5 cc  TRUE  5 cc
user2654764
źródło

Odpowiedzi:

129

Użyj paste.

 df$x <- paste(df$n,df$s)
 df
#   n  s     b    x
# 1 2 aa  TRUE 2 aa
# 2 3 bb FALSE 3 bb
# 3 5 cc  TRUE 5 cc
mnel
źródło
. @ thelatemail - Jak dodać znak specjalny między punktami danych za pomocą paste()? Na przykład powyżej xkolumna powinna zawierać dane jako 2-aa, then 3-bbi 5-cc.
Chetan Arvind Patil
8
. @ thelatemail - To zadziałało dla mnie:paste(df$n,df$s,sep="-")
Chetan Arvind Patil
2
jak pominąć NA, jeśli kolumna sma wartość NA? (Nie lubię widzieć, 3 NAczy df$s[2]=NA)
Cina
34

Aby wstawić separator:

df$x <- paste(df$n, "-", df$s)
Mała pszczółka
źródło
1
. @ LittleBee - dodaje spację między dwoma danymi. Na przykład końcowe dane wyjściowe to: A - Bzamiast A-B. Czy można usunąć tę dodatkową przestrzeń?
Chetan Arvind Patil
8
@ LittleBee - To zadziałało dla mnie:paste(df$n,df$s,sep="-")
Chetan Arvind Patil
5
użyj paste0 zamiast pasty
Ferroao
3
To nie da pożądanego wyniku: OP prosi o spację między elementami, a nie o inny separator (który, nawiasem mówiąc, lepiej byłoby umieścić jako separgument ...). Jednak druga odpowiedź, opublikowana prawie 4 lata wcześniej niż twoja, doskonale odpowiada na to pytanie.
Cath
16

Jak już wspomniano w komentarzach Uwe i UseR, ogólnym rozwiązaniem w tidyverseformacie byłoby użycie polecenia unite:

library(tidyverse)

n = c(2, 3, 5) 
s = c("aa", "bb", "cc") 
b = c(TRUE, FALSE, TRUE) 

df = data.frame(n, s, b) %>% 
  unite(x, c(n, s), sep = " ", remove = FALSE)
Quentin Perrier
źródło
2
Co to jest x w tym przykładzie?
Levi
@Levi, który xreprezentuje nazwę nowej kolumny zawierającej połączone wartości. Pomyśl o dplyrze mutate:df %>% dplyr::mutate(x = "your operations")
Vesanen
13

Niektóre przykłady z NA i ich usuwanie za pomocą Apply

n = c(2, NA, NA) 
s = c("aa", "bb", NA) 
b = c(TRUE, FALSE, NA) 
c = c(2, 3, 5) 
d = c("aa", NA, "cc") 
e = c(TRUE, NA, TRUE) 
df = data.frame(n, s, b, c, d, e)

paste_noNA <- function(x,sep=", ") {
gsub(", " ,sep, toString(x[!is.na(x) & x!="" & x!="NA"] ) ) }

sep=" "
df$x <- apply( df[ , c(1:6) ] , 1 , paste_noNA , sep=sep)
df
Ferroao
źródło
2
Jeśli chcesz korzystać z tidyrpakietu do odtworzenia oczekiwanej odpowiedzi na oryginalne pytanie byłoby to jedno-liner: tidyr::unite(df, x, n, s, sep = " ", remove = FALSE)[, c(names(df), "x")]. Jednak nie widzę powodu, aby to robić, ponieważ df$x <- paste(df$n,df$s)jest to znacznie prostsze.
Uwe
@Ferroao Cóż, odpowiedzi również nie powinny być zbyt ogólne, w przeciwnym razie każde pytanie miałoby tylko jedną gigantyczną odpowiedź zawierającą wszystko. Usunięcie NA nie było częścią prostego pytania OP, więc nie widzę, w jaki sposób ta dodatkowa złożoność zwiększa wartość prostego pastelub tidyr::unite.
avid_useR
@Ferroao Dzięki, uratowałeś mi życie. pls przenieś funkcję paste_noNA przed df $ x <-apply.
malajisi
11

Używając dplyr::mutate:

library(dplyr)
df <- mutate(df, x = paste(n, s)) 

df 
> df
  n  s     b    x
1 2 aa  TRUE 2 aa
2 3 bb FALSE 3 bb
3 5 cc  TRUE 5 cc
sbha
źródło
1
Nie, ponieważ już istnieją odpowiedzi, używasz wklejania , a nie mutacji .
zx8754
Pomyślałem, że demonstruję, jak można łączyć kolumny jako część pliku dplyr::mutate(). Przepraszam, tylko staram się być pomocny - nie będę już zanieczyszczać witryny i powstrzymać się od przyszłych postów.
sbha
Przepraszam, jeśli wyszło tak niegrzecznie. Problem OP nie jest rozwiązany przez użycie mutate , pytanie nie dotyczy tego, jak używać dplyr , ale jak łączyć wartości kolumn. Po prostu zaznaczam, że potrzebują pasty, a nie mutacji . Jeśli chcemy zademonstrować dplyr we właściwy sposób, użyj funkcji unite .
zx8754
9

Możemy użyć paste0 :

df$combField <- paste0(df$x, df$y)

Jeśli nie chcesz, aby w połączonym polu było wprowadzane żadne spacje. Jest to bardziej przydatne, jeśli planujesz użyć połączonego pola jako unikalnego identyfikatora, który reprezentuje kombinacje dwóch pól.

yanes
źródło
6

Zamiast

  • paste (spacje domyślne),
  • paste0(wymuś włączenie braku NAjako znaku) lub
  • unite (ograniczone do 2 kolumn i 1 separatora),

Proponuję alternatywę tak elastyczną, jak, paste0ale ostrożniejszą z NA:stringr::str_c

library(tidyverse)

# check the missing value!!
df <- tibble(
  n = c(2, 2, 8),
  s = c("aa", "aa", NA_character_),
  b = c(TRUE, FALSE, TRUE)
)

df %>% 
  mutate(
    paste = paste(n,"-",s,".",b),
    paste0 = paste0(n,"-",s,".",b),
    str_c = str_c(n,"-",s,".",b)
  ) %>% 

  # convert missing value to ""
  mutate(
    s_2=str_replace_na(s,replacement = "")
  ) %>% 
  mutate(
    str_c_2 = str_c(n,"-",s_2,".",b)
  )
#> # A tibble: 3 x 8
#>       n s     b     paste          paste0     str_c      s_2   str_c_2   
#>   <dbl> <chr> <lgl> <chr>          <chr>      <chr>      <chr> <chr>     
#> 1     2 aa    TRUE  2 - aa . TRUE  2-aa.TRUE  2-aa.TRUE  "aa"  2-aa.TRUE 
#> 2     2 aa    FALSE 2 - aa . FALSE 2-aa.FALSE 2-aa.FALSE "aa"  2-aa.FALSE
#> 3     8 <NA>  TRUE  8 - NA . TRUE  8-NA.TRUE  <NA>       ""    8-.TRUE

Utworzono 10.04.2020 r. Przez pakiet reprex (v0.3.0)

dodatkowa uwaga z str_cdokumentacji

Podobnie jak większość innych funkcji języka R, brakujące wartości są „zaraźliwe”: za każdym razem, gdy brakująca wartość jest łączona z innym ciągiem, zawsze będzie brakować wyniku. Służy str_replace_na()do konwersji NAna"NA"

avallecam
źródło
1
paste0(n,"-",s,".",b)i str_c(n,"-",s,".",b)są dokładnie takie same, oba używają domyślnego separatora, którym jest pusty ciąg ''. Nie wiem też, dlaczego pastejest „uporządkowany”, to znaczy, że nie lubisz spacji?
Axeman
paste0i str_cnie są dokładnie takie same. spójrz na te linki: (1) rdocumentation.org/packages/stringr/versions/1.3.1/topics/str_c (2) stackoverflow.com/questions/53118271/…
avallecam
O, rozumiem! Dzięki! To, jak się różnią, byłoby dobrym uzupełnieniem tej odpowiedzi (a str_cdokumentacja mogłaby być też bardziej wyraźna!).
Axeman
@Axeman dzięki za sugestię. Uprościłem odpowiedź i dodałem dodatkową uwagę na ten temat
avallecam
2

Istnieją inne świetne odpowiedzi, ale w przypadku, gdy nie znasz nazw kolumn lub liczby kolumn, które chcesz wcześniej połączyć, przydatne są następujące.

df = data.frame(x = letters[1:5], y = letters[6:10], z = letters[11:15])
colNames = colnames(df) # could be any number of column names here
df$newColumn = apply(df[, colNames, drop = F], MARGIN = 1, FUN = function(i) paste(i, collapse = ""))
Ben Ernest
źródło