Combinez deux ou plusieurs colonnes dans un dataframe dans une nouvelle colonne avec un nouveau nom


104

Par exemple si j'ai ceci:

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

Alors comment combiner les deux colonnes net sdans une nouvelle colonne nommée de xtelle sorte qu'elle ressemble à ceci:

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

Réponses:


129

Utilisez 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 - Comment ajouter un caractère spécial entre les points de données en utilisant paste()? Pour l'exemple ci-dessus, la xcolonne doit avoir des données comme 2-aa, puis 3-bbet 5-cc.
Chetan Arvind Patil

8
. @ thelatemail - Cela a fonctionné pour moi:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

2
comment pouvez-vous omettre NA si la colonne sa une valeur NA? (Je n'aime pas voir 3 NAsi df$s[2]=NA)
Cina

34

Pour insérer un séparateur:

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

1
. @ LittleBee - Cela ajoute un espace entre deux données. La sortie finale par exemple est comme: A - Bau lieu de A-B. Est-il possible de supprimer cet espace supplémentaire?
Chetan Arvind Patil

8
. @ LittleBee - Cela a fonctionné pour moi:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

5
utiliser paste0 au lieu de paste
Ferroao

3
Cela ne donnera pas la sortie désirée: OP demande un espace entre les éléments, pas un autre séparateur (qui, d'ailleurs, serait mieux mis comme separgument ...). L'autre réponse, postée près de 4 ans avant la vôtre, répond pourtant parfaitement à la question.
Cath

16

Comme déjà mentionné dans les commentaires de Uwe et UseR, une solution générale dans le tidyverseformat serait d'utiliser la commande 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'est-ce que x dans cet exemple?
Levi

@Levi, qui xreprésente le nom de la nouvelle colonne contenant les valeurs combinées. Pensez à dplyr's mutate:df %>% dplyr::mutate(x = "your operations")
Vesanen

13

Quelques exemples avec des NA et leur suppression à l'aide de 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
Si vous voulez utiliser le tidyrpackage pour reproduire la réponse attendue de la question initiale ce serait une seule ligne: tidyr::unite(df, x, n, s, sep = " ", remove = FALSE)[, c(names(df), "x")]. Cependant, je ne vois pas de raison de le faire car df$x <- paste(df$n,df$s)c'est beaucoup plus simple.
Uwe

@Ferroao Eh bien, les réponses ne devraient pas être trop générales non plus, sinon chaque question n'aurait qu'une seule réponse géante incorporant tout. La suppression des NA ne faisait pas partie de la simple question de OP, donc je ne vois pas comment cette complexité supplémentaire ajoute de la valeur à un simple pasteou tidyr::unite.
avid_useR

@Ferroao Merci, vous m'avez sauvé la vie. pls déplacer la fonction paste_noNA avant df $ x <-apply.
malajisi

11

Utilisation 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
Non, comme les réponses déjà existantes, vous utilisez coller , pas muter .
zx8754

Je pensais montrer comment les colonnes pouvaient être combinées dans le cadre d'un fichier dplyr::mutate(). Désolé, j'essaie juste d'être utile - je ne polluerai plus le site et je m'abstiendrai de publier de futurs messages.
sbha

Désolé, si cela s'est révélé impoli. Le problème d'OP n'est pas résolu en utilisant mutate , la question n'est pas de savoir comment utiliser dplyr , mais comment combiner les valeurs de colonne. Je fais simplement remarquer qu'ils ont besoin de coller et non de muter . Si nous voulons démontrer la manière correcte de dplyr est d' utiliser la fonction unite .
zx8754

9

Nous pouvons utiliser paste0 :

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

Si vous ne voulez aucun espace de remplissage introduit dans le champ concaténé. Ceci est plus utile si vous prévoyez d'utiliser le champ combiné comme un identifiant unique qui représente des combinaisons de deux champs.


6

Au lieu de

  • paste (espaces par défaut),
  • paste0 (forcer l'inclusion de manquant NA comme caractère) ou
  • unite (contraint à 2 colonnes et 1 séparateur),

Je suggérerais une alternative aussi flexible que paste0mais plus prudente avec 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

Créé le 2020-04-10 par le package reprex (v0.3.0)

note supplémentaire de str_c documentation

Comme la plupart des autres fonctions R, les valeurs manquantes sont «infectieuses»: chaque fois qu'une valeur manquante est combinée avec une autre chaîne, le résultat sera toujours manquant. Utilisez str_replace_na()pour convertir NAen"NA"


1
paste0(n,"-",s,".",b)et str_c(n,"-",s,".",b)sont exactement les mêmes, les deux utilisent un séparateur par défaut qui est la chaîne vide ''. Je ne sais pas non plus pourquoi pasteest «bien rangé», tu veux dire que tu n'aimes pas les espaces?
Axeman

paste0et str_cne sont pas exactement les mêmes. jetez un œil à ces liens: (1) rdocumentation.org/packages/stringr/versions/1.3.1/topics/str_c (2) stackoverflow.com/questions/53118271/…
avallecam

Ah, je vois! Merci! Leur différence serait un bon ajout à cette réponse (et la str_cdocumentation pourrait être plus explicite aussi!).
Axeman

@Axeman merci pour votre suggestion. J'ai simplifié la réponse et ajouté une note supplémentaire sur le problème
avallecam

2

Il existe d'autres bonnes réponses, mais dans le cas où vous ne connaissez pas les noms de colonnes ou le nombre de colonnes que vous souhaitez concaténer au préalable, ce qui suit est utile.

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 = ""))
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.