Объедините два или более столбца в фрейме данных в новый столбец с новым именем


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.
Четан Арвинд Патил

8
. @ thelatemail - Это сработало для меня:paste(df$n,df$s,sep="-")
Четан Арвинд Патил

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. Можно ли убрать это лишнее пространство?
Четан Арвинд Патил

9
. @ LittleBee - Это сработало для меня:paste(df$n,df$s,sep="-")
Четан Арвинд Патил

5
используйте paste0 вместо paste
Ferroao

3
Это не даст желаемого результата: OP запрашивает пробел между элементами, а не другой разделитель (который, кстати, лучше было бы поставить в качестве sepаргумента ...). Другой ответ, опубликованный почти за 4 года до вашего, однако, идеально отвечает на этот вопрос.
Кэт,

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, xпредставляющий имя нового столбца, содержащего комбинированные значения. Подумайте о dplyr's mutate:df %>% dplyr::mutate(x = "your operations")
Весанен

13

Некоторые примеры с НА и их удаление с помощью 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

2
Если вы хотите использовать tidyrпакет , чтобы воспроизвести ожидаемый ответ на первоначальный вопрос , это будет один вкладыш: tidyr::unite(df, x, n, s, sep = " ", remove = FALSE)[, c(names(df), "x")]. Однако я не вижу причин для этого, так как df$x <- paste(df$n,df$s)это намного проще.
Уве

@Ferroao Ну, ответы тоже не должны быть слишком общими, иначе на каждый вопрос был бы один гигантский ответ, включающий все. Удаление 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 не решается с помощью mutate , вопрос не в том, как использовать 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 с помощью пакета REPEX (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 = ""))
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.