Combine duas ou mais colunas em um dataframe em uma nova coluna com um novo nome

104

Por exemplo, se eu tiver este:

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

Então, como faço para combinar as duas colunas ne sem uma nova coluna chamada de xforma que se pareça com isto:

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

Respostas:

127

Use 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
fonte
. @ thelatemail - Como adicionar um caractere especial entre os pontos de dados usando paste()? Para o exemplo acima, a xcoluna deve ter dados como 2-aa, então 3-bbe 5-cc.
Chetan Arvind Patil
8
. @ thelatemail - Funcionou para mim:paste(df$n,df$s,sep="-")
Chetan Arvind Patil
2
como você pode omitir NA se a coluna stem valor NA? (Não gosto de ver 3 NAse df$s[2]=NA)
Cina
34

Para inserir um separador:

df$x <- paste(df$n, "-", df$s)
Abelhinha
fonte
1
. @ LittleBee - Adiciona um espaço entre dois dados. A saída final, por exemplo, é como: em A - Bvez de A-B. É possível remover esse espaço extra?
Chetan Arvind Patil
8
. @ LittleBee - Funcionou para mim:paste(df$n,df$s,sep="-")
Chetan Arvind Patil
5
use paste0 em vez de paste
Ferroao 02/11/17
3
Isso não dará a saída desejada: OP pede um espaço entre os elementos, não outro separador (que, a propósito, seria melhor colocar como o separgumento ...). A outra resposta, postada quase 4 anos antes da sua, é, no entanto, responder perfeitamente à pergunta.
Cath
16

Conforme já mencionado nos comentários de Uwe e UseR, uma solução geral no tidyverseformato seria usar o comando 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
fonte
2
O que é x neste exemplo?
Levi
@Levi, que xrepresenta o nome da nova coluna que contém os valores combinados. Pense em dplyr's mutate:df %>% dplyr::mutate(x = "your operations")
Vesanen
13

Alguns exemplos com NAs e sua remoção usando aplicar

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
fonte
2
Se você quiser usar o tidyrpacote para reproduzir a resposta esperada da pergunta original que este seria um one-liner: tidyr::unite(df, x, n, s, sep = " ", remove = FALSE)[, c(names(df), "x")]. No entanto, não vejo razão para fazer isso, pois df$x <- paste(df$n,df$s)é muito mais simples.
Uwe
@Ferroao Bem, as respostas não devem ser muito gerais, caso contrário, cada pergunta teria apenas uma resposta gigante incorporando tudo. A remoção de NAs não fazia parte da pergunta simples do OP, então não vejo como essa complexidade extra agrega valor a um pasteou simples tidyr::unite.
avid_useR de
@Ferroao Obrigado, você salvou minha vida. por favor mova a função paste_noNA antes de df $ x <-apply.
malajisi
11

Usando 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
fonte
1
Não, como respostas já existentes, você está usando colar , não modificar .
zx8754
Achei que estava demonstrando como as colunas podem ser combinadas como parte de um dplyr::mutate(). Desculpe, só estou tentando ser útil - não vou poluir mais o site e me abster de postagens futuras.
sbha
Desculpe, se saiu tão rude. O problema do OP não é resolvido usando mutate , a questão não é como usar dplyr , mas como combinar os valores das colunas. Estou simplesmente apontando que eles precisam colar, não sofrer mutação . Se queremos demonstrar o dplyr a maneira correta é usando a função unite .
zx8754
9

Podemos usar paste0 :

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

Se você não deseja que nenhum espaço de preenchimento seja introduzido no campo concatenado. Isso é mais útil se você estiver planejando usar o campo combinado como um id único que representa combinações de dois campos.

yanes
fonte
6

Ao invés de

  • paste (espaços padrão),
  • paste0(forçar a inclusão de ausente NAcomo personagem) ou
  • unite (restrito a 2 colunas e 1 separador),

Eu sugeriria uma alternativa tão flexível quanto, paste0porém mais cuidadosa com 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

Criado em 2020-04-10 pelo pacote reprex (v0.3.0)

nota extra da str_cdocumentação

Como a maioria das outras funções R, os valores ausentes são "infecciosos": sempre que um valor ausente é combinado com outra string, o resultado sempre estará ausente. Use str_replace_na()para converter NApara"NA"

avallecam
fonte
1
paste0(n,"-",s,".",b)e str_c(n,"-",s,".",b)são exatamente iguais, ambos usam um separador padrão que é a string vazia ''. Também não sei porque pasteé "arrumado", quer dizer que não gosta de espaços?
Axeman
paste0e str_cnão são exatamente iguais. dê uma olhada nestes links: (1) rdocumentation.org/packages/stringr/versions/1.3.1/topics/str_c (2) stackoverflow.com/questions/53118271/…
avallecam
Ah entendo! Obrigado! Como eles são diferentes seria um bom complemento para esta resposta (e a str_cdocumentação poderia ser mais explítica também!).
Axeman
@Axeman, obrigado por sua sugestão. Simplifiquei a resposta e acrescentei uma nota extra sobre o problema
avallecam de
2

Existem outras ótimas respostas, mas no caso em que você não sabe os nomes das colunas ou o número de colunas que deseja concatenar de antemão, o seguinte é útil.

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
fonte