Gabungkan dua atau lebih kolom dalam kerangka data ke dalam kolom baru dengan nama baru


104

Misalnya jika saya punya ini:

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

Lalu bagaimana cara menggabungkan kedua kolom tersebut ndan smenjadi kolom baru yang diberi nama xsedemikian rupa sehingga terlihat seperti ini:

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

Jawaban:


129

Gunakan 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

. @ thelatemail - Bagaimana cara menambahkan karakter khusus di antara titik data menggunakan paste()? Untuk contoh di atas, xkolom harus memiliki data sebagai 2-aa, lalu 3-bbdan 5-cc.
Chetan Arvind Patil

8
. @ thelatemail - Ini berhasil untuk saya:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

2
bagaimana Anda bisa menghilangkan NA jika kolom smemiliki nilai NA? (Saya tidak suka melihat 3 NAapakah df$s[2]=NA)
Cina

34

Untuk menyisipkan pemisah:

df$x <- paste(df$n, "-", df$s)

1
. @ LittleBee - Ini menambahkan spasi di antara dua data. Hasil akhir misalnya seperti: A - Bbukan A-B. Apakah mungkin untuk menghapus ruang ekstra ini?
Chetan Arvind Patil

8
. @ LittleBee - Ini berhasil untuk saya:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

5
gunakan paste0 alih-alih tempel
Ferroao

3
Ini tidak akan memberikan hasil yang diinginkan: OP meminta spasi di antara elemen, bukan pemisah lain (yang, omong-omong, akan lebih baik diletakkan sebagai separgumen ...). Jawaban lain, diposting hampir 4 tahun sebelum jawaban Anda, namun menjawab pertanyaan dengan sempurna.
Cath

16

Seperti yang telah disebutkan dalam komentar oleh Uwe dan UseR, solusi umum dalam tidyverseformat tersebut adalah dengan menggunakan perintah 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)

2
Apa x dalam contoh ini?
Levi

@Levi, yang xmewakili nama kolom baru yang berisi nilai gabungan. Pikirkan dplyr's mutate:df %>% dplyr::mutate(x = "your operations")
Vesanen

13

Beberapa contoh dengan NA dan penghapusannya menggunakan berlaku

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

2
Jika Anda ingin menggunakan tidyrpaket untuk mereproduksi jawaban yang diharapkan dari pertanyaan awal ini akan menjadi satu-kapal: tidyr::unite(df, x, n, s, sep = " ", remove = FALSE)[, c(names(df), "x")]. Namun, saya tidak melihat alasan untuk melakukannya karena df$x <- paste(df$n,df$s)jauh lebih sederhana.
Uwe

@Ferroao Ya, jawaban juga tidak boleh terlalu umum, jika tidak setiap pertanyaan hanya akan memiliki satu jawaban raksasa yang menggabungkan semuanya. Penghapusan NA bukanlah bagian dari pertanyaan sederhana OP, jadi saya tidak melihat bagaimana kompleksitas ekstra itu menambah nilai ke pasteatau tidyr::unite.
avid_useR

@Ferroao Terima kasih, Anda menyelamatkan hidup saya. tolong pindahkan fungsi paste_noNA sebelum df $ x <-apply.
malajisi

11

Menggunakan 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

1
Tidak, karena jawaban yang sudah ada, Anda menggunakan tempel , bukan mutasi .
zx8754

Saya pikir saya sedang mendemonstrasikan bagaimana kolom dapat digabungkan sebagai bagian dari a dplyr::mutate(). Maaf, hanya mencoba membantu - saya tidak akan mencemari situs ini lagi dan menjauhkan diri dari posting selanjutnya.
sbha

Maaf, jika ternyata tidak sopan. Masalah OP tidak diselesaikan dengan menggunakan mutate , pertanyaannya bukan tentang bagaimana menggunakan dplyr , tetapi bagaimana menggabungkan nilai kolom. Saya hanya menunjukkan bahwa mereka perlu pasta tidak bermutasi . Jika kita ingin mendemonstrasikan dplyr cara yang benar adalah menggunakan fungsi unite .
zx8754

9

Kita bisa menggunakan paste0 :

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

Jika Anda tidak ingin ada ruang padding yang dimasukkan dalam bidang gabungan. Ini lebih berguna jika Anda berencana menggunakan kolom gabungan sebagai id unik yang mewakili kombinasi dua kolom.


6

Dari pada

  • paste (spasi default),
  • paste0(memaksa dimasukkannya hilang NAsebagai karakter) atau
  • unite (dibatasi hingga 2 kolom dan 1 pemisah),

Saya menyarankan alternatif sefleksibel paste0tetapi lebih berhati-hati dengan 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

Dibuat pada 2020-04-10 oleh paket reprex (v0.3.0)

catatan tambahan dari str_cdokumentasi

Seperti kebanyakan fungsi R lainnya, nilai yang hilang bersifat "menular": setiap kali nilai yang hilang digabungkan dengan string lain, hasilnya akan selalu hilang. Gunakan str_replace_na()untuk mengonversi NAke"NA"


1
paste0(n,"-",s,".",b)dan str_c(n,"-",s,".",b)persis sama, keduanya menggunakan pemisah default yaitu string kosong ''. Saya juga tidak tahu kenapa paste"rapi", maksud Anda Anda tidak suka spasi?
Axeman


Ah saya mengerti! Terima kasih! Perbedaannya akan menjadi tambahan yang bagus untuk jawaban ini (dan str_cdokumentasinya juga bisa lebih eksplisit!).
Axeman

@Axeman terima kasih atas saran Anda. Saya telah menyederhanakan jawabannya dan menambahkan catatan tambahan tentang masalah ini
avallecam

2

Ada jawaban bagus lainnya, tetapi dalam kasus di mana Anda tidak tahu nama kolom atau jumlah kolom yang ingin Anda gabungkan sebelumnya, berikut ini berguna.

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 = ""))
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.