Об’єднайте два або більше стовпців у кадрі даних у новий стовпець з новою назвою


104

Наприклад, якщо у мене це є:

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

Відповіді:


129

Використовуйте 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="-")
Четан Арвінд Патіл

2
як можна опустити NA, якщо стовпець sмає значення NA? (Я не хотів би бачити , 3 NAякщо df$s[2]=NA)
Cina

34

Для вставки роздільника:

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

1
. @ LittleBee - це додає пробіл між двома даними. Наприклад, підсумковий результат виглядає так: A - Bзамість A-B. Чи можливо видалити цей додатковий простір?
Chetan Arvind Patil

8
. @ LittleBee - Це працювало для мене:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

5
використовувати paste0 замість пасти
Ferroao

3
Це не дасть бажаного результату: OP запитує пробіл між елементами, а не інший роздільник (що, до речі, краще було б поставити як sepаргумент ...). Інша відповідь, опублікована майже за чотири роки до вашої, проте чудово відповідає на питання.
Кат

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
Що таке х у цьому прикладі?
Леві

@Levi, що xпредставляє назву нового стовпця, який містить об'єднані значення. Подумайте про dplyr's mutate:df %>% dplyr::mutate(x = "your operations")
Vesanen

13

Деякі приклади з NA та їх вилучення з використанням

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)це набагато простіше.
Уве

@Ferroao Добре, що відповіді також не повинні бути надто загальними, інакше на кожне запитання буде лише одна гігантська відповідь, що включає все. Видалення НС не було частиною простого питання ОП, тому я не бачу, як ця додаткова складність додає значення простому pasteабо tidyr::unite.
avid_useR

@Ferroao Спасибі, ти врятував мені життя. pls перемістіть функцію paste_noNA перед df $ x <-прикладати.
маладжисі

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 , використовуємо функцію unite .
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"охайний", ти маєш на увазі, що ти не любиш пробіли?
лісоруб

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 = ""))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.