Combinar dos o más columnas en un marco de datos en una nueva columna con un nuevo nombre


104

Por ejemplo, si tengo esto:

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

Entonces, ¿cómo combino las dos columnas ny sen una nueva columna con el nombre de xque se ve así:

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

Respuestas:


128

Utilice 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 - ¿Cómo agregar un carácter especial entre puntos de datos usando paste()? En el ejemplo anterior, la xcolumna debe tener datos como 2-aa, luego 3-bby 5-cc.
Chetan Arvind Patil

8
. @ thelatemail - Esto funcionó para mí:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

2
¿Cómo se puede omitir NA si la columna stiene un valor NA? (No me gusta ver 3 NAsi df$s[2]=NA)
Cina

34

Para insertar un separador:

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

1
. @ LittleBee: agrega un espacio entre dos datos. El resultado final, por ejemplo, es como: en A - Blugar de A-B. ¿Es posible eliminar este espacio extra?
Chetan Arvind Patil

8
. @ LittleBee - Esto funcionó para mí:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

5
use paste0 en lugar de paste
Ferroao

3
Esto no dará el resultado deseado: OP solicita un espacio entre los elementos, no otro separador (que, por cierto, sería mejor ponerlo como separgumento ...). Sin embargo, la otra respuesta, publicada casi 4 años antes que la suya, responde perfectamente a la pregunta.
Cath

16

Como ya se mencionó en los comentarios de Uwe y UseR, una solución general en el tidyverseformato sería usar el 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)

2
¿Qué es x en este ejemplo?
Levi

@Levi, que xrepresenta el nombre de la nueva columna que contiene los valores combinados. Piense en dplyr's mutate:df %>% dplyr::mutate(x = "your operations")
Vesanen

13

Se aplican algunos ejemplos con NA y su eliminación utilizando

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
Si desea utilizar el tidyrpaquete de reproducir la respuesta esperada de la pregunta original que esto sería una sola línea: tidyr::unite(df, x, n, s, sep = " ", remove = FALSE)[, c(names(df), "x")]. Sin embargo, no veo una razón para hacerlo, ya que df$x <- paste(df$n,df$s)es mucho más simple.
Uwe

@Ferroao Bueno, las respuestas tampoco deberían ser demasiado generales, de lo contrario, cada pregunta tendría una respuesta gigante incorporando todo. La eliminación de NA no era parte de la pregunta simple de OP, por lo que no veo cómo esa complejidad adicional agrega valor a una simple pasteo tidyr::unite.
avid_useR

@Ferroao Gracias, me salvaste la vida. Por favor, mueva la función 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

1
No, como las respuestas ya existentes, está usando pegar , no mutar .
zx8754

Pensé que estaba demostrando cómo las columnas se pueden combinar como parte de un dplyr::mutate(). Lo siento, solo trato de ser útil, ya no contaminaré el sitio y me abstendré de publicaciones futuras.
sbha

Lo siento, si salió como grosero. El problema de OP no se resuelve usando mutate , la pregunta no es cómo usar dplyr , sino cómo combinar valores de columna. Simplemente estoy señalando que necesitan pegar, no mutar . Si queremos demostrar dplyr, la forma correcta es usar la función unir .
zx8754

9

Podemos usar paste0 :

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

Si no desea que se introduzca ningún espacio de relleno en el campo concatenado. Esto es más útil si planea usar el campo combinado como una identificación única que representa combinaciones de dos campos.


6

En vez de

  • paste (espacios predeterminados),
  • paste0(forzar la inclusión de la falta NAcomo personaje) o
  • unite (restringido a 2 columnas y 1 separador),

Sugeriría una alternativa tan flexible como paste0pero más cuidadosa con 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

Creado el 10/04/2020 por el paquete reprex (v0.3.0)

nota adicional de la str_cdocumentación

Como la mayoría de las otras funciones R, los valores perdidos son "infecciosos": siempre que un valor faltante se combine con otra cadena, el resultado siempre faltará. Utilizar str_replace_na()para convertir NAa"NA"


1
paste0(n,"-",s,".",b)y str_c(n,"-",s,".",b)son exactamente iguales, ambos usan un separador predeterminado que es la cadena vacía ''. Tampoco sé por qué pastees "ordenado", ¿quieres decir que no te gustan los espacios?
Axeman

paste0y str_cno son exactamente iguales. eche un vistazo a estos enlaces: (1) rdocumentation.org/packages/stringr/versions/1.3.1/topics/str_c (2) stackoverflow.com/questions/53118271/…
avallecam

¡Ah, ya veo! ¡Gracias! La forma en que son diferentes sería una buena adición a esta respuesta (¡y la str_cdocumentación también podría ser más explícita!).
Axeman

@Axeman gracias por tu sugerencia. He simplificado la respuesta y agregué una nota adicional sobre el problema
avallecam

2

Hay otras excelentes respuestas, pero en el caso de que no sepa los nombres de las columnas o el número de columnas que desea concatenar de antemano, lo siguiente es ú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 = ""))
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.