跨特定列按行连接数据框。

38

我有一个数据框,它有几列,当将它们(按行)串联为字符串时,可以使我将数据框分成所需的形式。

> str(data)
'data.frame':   680420 obs. of  10 variables:
 $ A              : chr  "2011-01-26" "2011-01-26" "2011-02-09" "2011-02-09" ...
 $ B              : chr  "2011-01-26" "2011-01-27" "2011-02-09" "2011-02-10" ...
 $ C              : chr  "2011-01-26" "2011-01-26" "2011-02-09" "2011-02-09" ...
 $ D              : chr  "AAA" "AAA" "BCB" "CCC" ...
 $ E              : chr  "A00001" "A00002" "B00002" "B00001" ...
 $ F              : int  9 9 37 37 37 37 191 191 191 191 ...
 $ G              : int  NA NA NA NA NA NA NA NA NA NA ...
 $ H              : int  4 4 4 4 4 4 4 4 4 4 ...
每行数据,我想将列F、E、D和C中的数据连接成一个字符串(使用下划线字符作为分隔符)。以下是我的不成功尝试:
data$id <- sapply(as.data.frame(cbind(data$F,data$E,data$D,data$C)), paste, sep="_")

以下是不希望的结果:

  > str(data)
    'data.frame':   680420 obs. of  10 variables:
     $ A              : chr  "2011-01-26" "2011-01-26" "2011-02-09" "2011-02-09" ...
     $ B              : chr  "2011-01-26" "2011-01-27" "2011-02-09" "2011-02-10" ...
     $ C              : chr  "2011-01-26" "2011-01-26" "2011-02-09" "2011-02-09" ...
     $ D              : chr  "AAA" "AAA" "BCB" "CCC" ...
     $ E              : chr  "A00001" "A00002" "B00002" "B00001" ...
     $ F              : int  9 9 37 37 37 37 191 191 191 191 ...
     $ G              : int  NA NA NA NA NA NA NA NA NA NA ...
     $ H              : int  4 4 4 4 4 4 4 4 4 4 ...
     $ id             : chr [1:680420, 1:4] "9" "9" "37" "37" ...
      ..- attr(*, "dimnames")=List of 2
      .. ..$ : NULL
      .. ..$ : chr  "V1" "V2" "V3" "V4"

任何帮助都将不胜感激。

3个回答

68

尝试一下

 data$id <- paste(data$F, data$E, data$D, data$C, sep="_")

相反,向量化代码的美妙之处在于您不需要逐行循环或循环等效的*apply函数。

编辑 更好的方法是

 data <- within(data,  id <- paste(F, E, D, C, sep=""))

哇,那真是快速而准确。看起来我过于复杂化了这个过程。我真的在努力摆脱完全“循环依赖”,并且仍在学习欣赏向量化代码。 - Jubbles
2
并尝试使用 with(data, paste(...)) 来使代码更加简洁。 - Richie Cotton
5
正确。或者甚至将 within() 视为 with() 的不那么受欢迎的表兄弟。我已相应地修改了我的答案。 - Dirk Eddelbuettel
2
这就是 within 的不同之处吗?!(为什么它不被命名为 with(..., modify=TRUE) 呢?) - smci
如果您使用 data$id <- paste(data[, c(1)], data[,c(2)]),但是代码的行为与预期不符,那么这里是否有什么遗漏的地方? - Parsa
显示剩余2条评论

13

使用tidyr包的unite函数:

require(tidyr)
data <- data %>% unite(id, F, E, D, C, sep = '_')

第一个参数是所需的名称,从下一个参数到sep之前的所有参数都将被连接为一列。


3
当我需要按组合折叠动态向量时,这种方法是唯一能够始终如一地工作的方法:mycols <- c("F","E","D","C") data <- data %>% unite_("id", mycols, sep = "_") - jessi

7

stringr::str_c()paste()都可以使用。

require(stringr)
data <- within(data, str_c(F,E,D,C, sep="_")

否则。
data <- within(data, paste(F,E,D,C, sep="_")

(stringr 在处理大型数据集时具有更好的性能)


1
@那个恶意降低评分的人:可以使用stringr::str_c,没有人说过不行。你有什么问题? - smci

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接