连接数据帧的行

Sam*_*Sam 31 r vector concatenation paste r-factor

我想采用带有字符和数字的数据框,并将每行的所有元素连接成一个字符串,该字符串将作为单个元素存储在向量中.作为一个例子,我创建一个字母和数字的数据框,然后我想通过粘贴函数连接第一行,并希望返回值"A1"

df <- data.frame(letters = LETTERS[1:5], numbers = 1:5)
df

##   letters numbers
## 1       A       1
## 2       B       2
## 3       C       3
## 4       D       4
## 5       E       5

paste(df[1,], sep =".")
## [1] "1" "1"
Run Code Online (Sandbox Code Playgroud)

因此,粘贴将行的每个元素转换为一个整数,该整数对应于"相应级别的索引",就像它是一个因子一样,并且它保持长度为2的向量.(我知道/相信被强制为字符的因素会以这种方式运行,但由于R根本没有存储df [1,]作为因素(由is.factor()测试,我无法验证它实际上是一个级别的索引)

is.factor(df[1,])
## [1] FALSE
is.vector(df[1,])
## [1] FALSE
Run Code Online (Sandbox Code Playgroud)

因此,如果它不是一个向量,那么它的行为很奇怪,但我无法将它强制转换为向量

> is.vector(as.vector(df[1,]))
[1] FALSE
Run Code Online (Sandbox Code Playgroud)

使用as.character似乎对我的尝试没有帮助

谁能解释这种行为?

seb*_*n-c 55

虽然其他人已经关注你的代码无法正常工作的原因以及如何改进它,但我将尝试更多地关注获得你想要的结果.根据您的描述,您似乎可以使用粘贴轻松实现您想要的效果:

df <- data.frame(letters = LETTERS[1:5], numbers = 1:5, stringsAsFactors=FALSE)
paste(df$letters, df$numbers, sep=""))

## [1] "A1" "B2" "C3" "D4" "E5"
Run Code Online (Sandbox Code Playgroud)

如果您不想使用参数,可以使用更改df$letters为字符.df$letters <- as.character(df$letters)stringsAsFactors

但是我们假设这不是你想要的.假设您有数百列,并且希望将它们全部粘贴在一起.我们也可以用你最小的例子做到这一点:

df_args <- c(df, sep="")
do.call(paste, df_args)

## [1] "A1" "B2" "C3" "D4" "E5"
Run Code Online (Sandbox Code Playgroud)

编辑:替代方法和解释:

我意识到你遇到的问题是你正在使用一个因素而你正在使用sep参数而不是collapse(正如@adibender选中的那样).区别在于sep在两个单独的向量之间collapse给出分隔符,并在向量内给出分隔符.使用时df[1,],提供单个向量paste,因此必须使用该collapse参数.使用您获取每一行并连接它们的想法,以下代码行将完全按照您的要求执行:

apply(df, 1, paste, collapse="")
Run Code Online (Sandbox Code Playgroud)

好的,现在解释一下:

为什么不行as.list

as.list将对象转换为列表.所以它确实有效.它会将您的数据帧转换为列表,然后忽略该sep=""参数.c将对象组合在一起 从技术上讲,数据框只是一个列表,其中每列都是一个元素,所有元素必须具有相同的长度.因此,当我将其与sep=""它结合使用时,它只会成为一个常规列表,其中数据框的列为元素.

为何使用do.call

do.call允许您使用命名列表作为参数调用函数.你不能直接抛出列表paste,因为它不喜欢数据帧.它专为连接矢量而设计.所以请记住,这dfargs是一个包含字母向量,数字向量和sep的列表,它是一个仅包含""的长度为1的向量.当我使用时do.call,产生的粘贴功能基本上是paste(letters, numbers, sep).
但是,如果我的原始数据框有列,"letters", "numbers", "squigs", "blargs"之后我像之前一样添加了分隔符呢?然后粘贴功能通过do.call如下所示:

paste(letters, numbers, squigs, blargs, sep)
Run Code Online (Sandbox Code Playgroud)

所以你看它适用于任意数量的列.


小智 5

对于那些使用 library(tidyverse) 的人,你可以简单地使用 unite 函数。

 new.df<-df%>%
 unite(together, letters, numbers, sep="")
Run Code Online (Sandbox Code Playgroud)

这将为您提供一个名为“一起”的新列,其中包含 A1、B2 等

  • Tidyverse 是一组软件包。试试 `?tidyverse::unite` —— 什么都没有。对于只想使用解决手头问题而不想加载整个包的人来说,很高兴知道他们可以只加载 tidyr。顺便说一句,我不是在批评我赞成的答案,只是建议改进。 (2认同)