Combina due o più colonne in un dataframe in una nuova colonna con un nuovo nome


104

Ad esempio, se ho questo:

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

Quindi come combino le due colonne ne sin una nuova colonna denominata in modo xtale che assomigli a questo:

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

Risposte:


129

Usa 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 - Come aggiungere un carattere speciale tra i punti dati utilizzando paste()? Per l'esempio precedente, la xcolonna dovrebbe contenere i dati come 2-aa, quindi 3-bbe 5-cc.
Chetan Arvind Patil

8
. @ thelatemail - Questo ha funzionato per me:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

2
come puoi omettere NA se la colonna sha un valore NA? (Non mi piace vedere 3 NAse df$s[2]=NA)
Cina

34

Per inserire un separatore:

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

1
. @ LittleBee - Questo aggiunge uno spazio tra due dati. L'output finale, ad esempio, è come: A - Binvece di A-B. È possibile rimuovere questo spazio aggiuntivo?
Chetan Arvind Patil

8
. @ LittleBee - Questo ha funzionato per me:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

5
usa paste0 invece di paste
Ferroao

3
Questo non darà l'output desiderato: OP chiede uno spazio tra gli elementi, non un altro separatore (che, a proposito, sarebbe meglio mettere come separgomento ...). L'altra risposta, postata quasi 4 anni prima della tua, risponde però perfettamente alla domanda.
Cath

16

Come già accennato nei commenti di Uwe e UseR, una soluzione generale nel tidyverseformato sarebbe quella di utilizzare il 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
Cos'è x in questo esempio?
Levi

@Levi, che xrappresenta il nome della nuova colonna che contiene i valori combinati. Pensa ai dplyr mutate:df %>% dplyr::mutate(x = "your operations")
Vesanen il

13

Alcuni esempi con NA e la loro rimozione utilizzando 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
Se si desidera utilizzare il tidyrpacchetto per riprodurre la risposta attesa della domanda originale questo sarebbe un one-liner: tidyr::unite(df, x, n, s, sep = " ", remove = FALSE)[, c(names(df), "x")]. Tuttavia, non vedo un motivo per farlo in quanto df$x <- paste(df$n,df$s)è molto più semplice.
Uwe

@Ferroao Bene, neanche le risposte dovrebbero essere troppo generiche, altrimenti ogni domanda avrebbe solo una risposta gigante che incorpora tutto. La rimozione di NA non faceva parte della semplice domanda di OP, quindi non vedo come quella complessità extra aggiunga valore a un semplice pasteo tidyr::unite.
avid_useR

@Ferroao Grazie, mi hai salvato la vita. pls sposta la funzione paste_noNA prima di df $ x <-apply.
malajisi

11

Utilizzando 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, come risposte già esistenti, stai usando incolla , non muta .
zx8754

Pensavo di dimostrare come combinare le colonne come parte di un file dplyr::mutate(). Mi dispiace, cerco solo di essere d'aiuto - non inquinerò più il sito e mi asterrò da futuri post.
sbha

Scusa, se è stato maleducato. Il problema di OP non viene risolto utilizzando mutate , la domanda non riguarda come utilizzare dplyr , ma come combinare i valori delle colonne. Sto semplicemente sottolineando che devono incollare non mutare . Se vogliamo dimostrare che il modo corretto di dplyr sta usando la funzione unite .
zx8754

9

Possiamo usare paste0 :

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

Se non vuoi che alcuno spazio di riempimento venga introdotto nel campo concatenato. Ciò è più utile se si prevede di utilizzare il campo combinato come ID univoco che rappresenta le combinazioni di due campi.


6

Invece di

  • paste (spazi predefiniti),
  • paste0(forza l'inclusione di mancante NAcome carattere) o
  • unite (vincolato a 2 colonne e 1 separatore),

Suggerirei un'alternativa flessibile come paste0ma più attenta 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

Creato il 10-04-2020 dal pacchetto reprex (v0.3.0)

nota extra dalla str_cdocumentazione

Come la maggior parte delle altre funzioni R, i valori mancanti sono "contagiosi": ogni volta che un valore mancante viene combinato con un'altra stringa, il risultato sarà sempre mancante. Utilizzare str_replace_na()per convertire NAin"NA"


1
paste0(n,"-",s,".",b)e str_c(n,"-",s,".",b)sono esattamente gli stessi, entrambi usano un separatore predefinito che è la stringa vuota ''. Inoltre non so perché pasteè "ordinato", vuoi dire che non ti piacciono gli spazi?
Axeman

paste0e str_cnon sono esattamente la stessa cosa. date un'occhiata a questi link: (1) rdocumentation.org/packages/stringr/versions/1.3.1/topics/str_c (2) stackoverflow.com/questions/53118271/...
avallecam

Ah capisco! Grazie! Il modo in cui sono diversi sarebbe una buona aggiunta a questa risposta (e anche la str_cdocumentazione potrebbe essere più esplicita!).
Axeman

@ Axeman, grazie per il tuo suggerimento. Ho semplificato la risposta e ho aggiunto una nota in più sul problema
avallecam

2

Ci sono altre ottime risposte, ma nel caso in cui non si conoscano i nomi delle colonne o il numero di colonne che si desidera concatenare in anticipo, è utile quanto segue.

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 = ""))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.