รวมคอลัมน์สองคอลัมน์ขึ้นไปใน dataframe เป็นคอลัมน์ใหม่โดยใช้ชื่อใหม่


106

ตัวอย่างเช่นถ้าฉันมีสิ่งนี้:

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

แล้วฉันจะรวมทั้งสองคอลัมน์nและsในคอลัมน์ใหม่ชื่อxดังกล่าวว่ามีลักษณะเช่นนี้

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

คำตอบ:


130

ใช้ 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 - วิธีเพิ่มอักขระพิเศษระหว่างจุดข้อมูลโดยใช้paste()? ตัวอย่างข้างต้นxคอลัมน์ควรมีข้อมูลเป็น2-aaแล้วและ3-bb 5-cc
Chetan Arvind Patil

8
. @ thelatemail - สิ่งนี้ใช้ได้ผลสำหรับฉัน:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

2
คุณจะละ NA ได้อย่างไรถ้าคอลัมน์sมีค่า NA (ฉันไม่ชอบดู3 NAว่าdf$s[2]=NA)
Cina

36

สำหรับการแทรกตัวคั่น:

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

1
. @ LittleBee - เพิ่มช่องว่างระหว่างสองข้อมูล ผลลัพธ์สุดท้ายเช่น: A - BแทนA-B. เป็นไปได้หรือไม่ที่จะเอาช่องว่างนี้ออก
Chetan Arvind Patil

9
. @ LittleBee - สิ่งนี้ได้ผลสำหรับฉัน:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

5
ใช้ paste0 แทนการวาง
Ferroao

3
สิ่งนี้จะไม่ให้ผลลัพธ์ที่ต้องการ: OP ขอช่องว่างระหว่างองค์ประกอบไม่ใช่ตัวคั่นอื่น (ซึ่งจะดีกว่าใส่เป็นsepอาร์กิวเมนต์ ... ) คำตอบอื่น ๆ ที่โพสต์ไว้ก่อนหน้าคุณเกือบ 4 ปี แต่ตอบคำถามได้อย่างสมบูรณ์แบบ
Cath

16

ดังที่ได้กล่าวไว้แล้วในความคิดเห็นของ Uwe และ UseR วิธีแก้ปัญหาทั่วไปในtidyverseรูปแบบจะใช้คำสั่ง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
x ในตัวอย่างนี้คืออะไร?
Levi

@ Levi ซึ่งxแสดงถึงชื่อของคอลัมน์ใหม่ที่มีค่ารวม นึกถึง dplyr mutate:df %>% dplyr::mutate(x = "your operations")
Vesanen

13

ตัวอย่างบางส่วนที่มี NAs และการนำออกโดยใช้ใช้

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
หากคุณต้องการใช้แพคเกจที่จะทำซ้ำคำตอบที่คาดหวังของคำถามเดิมนี้จะเป็นหนึ่งซับ:tidyr tidyr::unite(df, x, n, s, sep = " ", remove = FALSE)[, c(names(df), "x")]อย่างไรก็ตามฉันไม่เห็นเหตุผลที่จะทำเช่นdf$x <- paste(df$n,df$s)นั้นง่ายกว่ามาก
Uwe

@ เฟอร์โรโอคำตอบไม่ควรกว้างเกินไปเช่นกันมิฉะนั้นทุกคำถามจะมีคำตอบขนาดใหญ่เพียงคำตอบเดียวที่รวมทุกอย่าง การลบ NA ไม่ได้เป็นส่วนหนึ่งของคำถามง่ายๆของ OP ดังนั้นฉันจึงไม่เห็นว่าความซับซ้อนพิเศษนั้นเพิ่มมูลค่าให้กับคำง่ายๆpasteหรือtidyr::unite.
avid_useR

@ Ferroao ขอบคุณคุณช่วยชีวิตฉัน กรุณาย้ายฟังก์ชัน paste_noNA ก่อน df $ x <-apply
malajisi

11

ใช้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
ไม่เป็นที่มีอยู่แล้วคำตอบที่คุณกำลังใช้วางไม่กลายพันธุ์
zx8754

ฉันคิดว่าฉันกำลังสาธิตวิธีรวมคอลัมน์เป็นส่วนหนึ่งของไฟล์dplyr::mutate(). ขอโทษนะแค่พยายามทำตัวให้เป็นประโยชน์ - ฉันจะไม่สร้างมลพิษให้กับไซต์อีกต่อไปและงดเว้นการโพสต์ในอนาคต
sbha

ขออภัยถ้ามันออกมาหยาบคาย ปัญหาของ OP ไม่ได้แก้ไขโดยใช้กลายพันธุ์คำถามไม่ได้เกี่ยวกับวิธีการใช้dplyrแต่วิธีการที่จะรวมค่าของคอลัมน์ ฉันเพียงแค่การชี้ให้เห็นว่าพวกเขาจำเป็นต้องวางไม่กลายพันธุ์ ถ้าเราต้องการที่จะแสดงให้เห็นถึงdplyrวิธีที่ถูกต้องคือการใช้ฟังก์ชั่นรวมกัน
zx8754

9

เราสามารถใช้paste0 :

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

หากคุณไม่ต้องการให้มีการเพิ่มพื้นที่ว่างในช่องที่ต่อกัน สิ่งนี้มีประโยชน์มากขึ้นหากคุณกำลังวางแผนที่จะใช้ฟิลด์ที่รวมกันเป็นรหัสเฉพาะที่แสดงถึงการผสมของสองฟิลด์


6

แทน

  • paste (ช่องว่างเริ่มต้น)
  • paste0(บังคับให้รวมส่วนที่ขาดหายไปNAเป็นอักขระ) หรือ
  • unite (จำกัด ไว้ที่ 2 คอลัมน์และ 1 ตัวคั่น)

ผมขอแนะนำให้เป็นทางเลือกที่เป็นความยืดหยุ่นเป็นpaste0แต่ระมัดระวังมากขึ้นด้วย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

สร้างเมื่อ 2020-04-10 โดยแพ็คเกจ reprex (v0.3.0)

หมายเหตุพิเศษจากstr_cเอกสารประกอบ

เช่นเดียวกับฟังก์ชัน R อื่น ๆ ส่วนใหญ่ค่าที่หายไปคือ "ติดเชื้อ": เมื่อใดก็ตามที่ค่าที่ขาดหายไปรวมกับสตริงอื่นผลลัพธ์จะหายไปเสมอ ใช้str_replace_na()เพื่อแปลงNAเป็นไฟล์"NA"


1
paste0(n,"-",s,".",b)และstr_c(n,"-",s,".",b)เหมือนกัน''ทุกประการทั้งคู่ใช้ตัวคั่นเริ่มต้นซึ่งเป็นสตริงว่าง ฉันก็ไม่รู้เหมือนกันว่าทำไมpaste"เป็นระเบียบ" คุณหมายความว่าคุณไม่ชอบเว้นวรรค?
Axeman

paste0และstr_cไม่เหมือนกันทุกประการ ดูลิงค์เหล่านี้: (1) rdocumentation.org/packages/stringr/versions/1.3.1/topics/str_c (2) stackoverflow.com/questions/53118271/…
avallecam

ฉันเห็น! ขอบคุณ! วิธีที่แตกต่างกันจะเป็นส่วนเสริมที่ดีสำหรับคำตอบนี้ (และstr_cเอกสารประกอบอาจมีความชัดเจนมากขึ้นด้วย!)
Axeman

@Axeman ขอบคุณสำหรับข้อเสนอแนะของคุณ ฉันได้ปรับคำตอบให้ง่ายขึ้นพร้อมเพิ่มหมายเหตุพิเศษเกี่ยวกับปัญหา
avallecam

2

มีคำตอบที่ดีอื่น ๆ แต่ในกรณีที่คุณไม่ทราบชื่อคอลัมน์หรือจำนวนคอลัมน์ที่คุณต้องการเชื่อมต่อไว้ก่อนสิ่งต่อไปนี้มีประโยชน์

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 = ""))
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.