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
user2654764
la source

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
mnel
la source
. @ 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)
Petite abeille
la source
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)
Quentin Perrier
la source
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
Ferroao
la source
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
sbha
la source
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.

yanes
la source
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"

Avallecam
la source
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 = ""))
Ben Ernest
la source