将数据框中的两个或更多列合并为具有新名称的新列


104

例如,如果我有这个:

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

那么如何合并两列n,并s进入一个名为新列x,使得它看起来是这样的:

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

Answers:


129

使用 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-如何使用来在数据点之间添加特殊字符paste()?对于上面的示例,xcolumn的数据应为2-aa,然后为3-bb5-cc
Chetan Arvind Patil '10

8
。@ thelatemail-这对我有用:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

2
如果列s具有NA值,如何省略NA ?(我不喜欢看3 NA是否df$s[2]=NA
支那

34

对于插入分隔符:

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

1
。@ LittleBee-这在两个数据之间添加了一个空格。例如,最终输出类似于:A - B而不是A-B。是否可以删除此多余的空间?
Chetan Arvind Patil '10

8
。@ LittleBee-这对我有用:paste(df$n,df$s,sep="-")
Chetan Arvind Patil

5
使用paste0代替粘贴
Ferroao

3
这不会提供所需的输出:OP要求在元素之间留一个空格,而不是另一个分隔符(顺便说一下,最好将其作为sep参数...)。另一个答案比您的答案早了将近四年,但是它可以完美地回答这个问题。
Cath

16

正如Uwe和UseR的评论中已经提到的,该tidyverse格式的一般解决方案是使用以下命令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
在这个例子中x是多少?
李维

@Levi,x代表包含组合值的新列的名称。想想dplyr的问题mutatedf %>% dplyr::mutate(x = "your operations")
Vesanen

13

NA的一些示例及其使用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
如果您想使用该tidyr软件包来重现原始问题的预期答案,那将是一个单行代码:tidyr::unite(df, x, n, s, sep = " ", remove = FALSE)[, c(names(df), "x")]。但是,我认为这样做没有理由df$x <- paste(df$n,df$s)更简单。
Uwe

@Ferroao好吧,答案也不应该太笼统,否则每个问题都会有一个包含所有内容的巨大答案。删除NA并不是OP的简单问题的一部分,因此我看不到额外的复杂性如何为简单的paste或增加价值tidyr::unite
avid_useR

@Ferroao谢谢,您救了我的命。请在df $ x <-apply之前移动paste_noNA函数。
malajisi19年

11

使用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
不,正如已经存在的答案一样,您正在使用粘贴而不是mutate
zx8754

我以为我正在演示如何将列合并为的一部分dplyr::mutate()。抱歉,只想提供帮助-我不会再污染该网站,也不会再发表任何帖子。
sbha

抱歉,如果它不礼貌地出现。OP的问题不是通过使用mutate解决的,问题不是关于如何使用dplyr,而是关于如何组合列值。我只是指出他们需要粘贴而不是变异。如果我们想演示dplyr的正确方法是使用unite函数
zx8754

9

我们可以使用paste0

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

如果您不想在连接字段中引入任何填充空间。如果您打算将组合字段用作表示两个字段组合的唯一ID,则此功能将更为有用。


6

代替

  • paste (默认空格),
  • paste0(强制将缺失内容包含在内NA)或
  • unite (限于2列和1个分隔符),

我建议另一种方法尽可能灵活,paste0但要谨慎一些NAstringr::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

reprex软件包(v0.3.0)创建于2020-04-10

str_c文档中的额外说明

像大多数其他R函数一样,缺失值是“传染性的”:每当缺失值与另一个字符串组合时,结果总是会缺失。使用str_replace_na()转换NA"NA"


1
paste0(n,"-",s,".",b)并且str_c(n,"-",s,".",b)完全相同,都使用默认的分隔符,即空字符串''。我也不知道为什么paste要“整洁”,你的意思是你不喜欢空格?
Axeman


啊,我明白了!谢谢!它们的不同之处将是此答案的一个很好的补充(并且str_c文档也可能更加具体!)。
Axeman

@Axeman感谢您的建议。我简化了答案,并
为此

2

还有其他一些很好的答案,但是如果您不知道要预先连接的列名或列数,则可以使用以下内容。

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 = ""))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.