连接数据帧的行

时间:2012-12-19 01:07:35

标签: 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"

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

is.factor(df[1,])
## [1] FALSE
is.vector(df[1,])
## [1] FALSE

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

> is.vector(as.vector(df[1,]))
[1] FALSE

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

任何人都可以解释这种行为吗?

4 个答案:

答案 0 :(得分:50)

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

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

## [1] "A1" "B2" "C3" "D4" "E5"

如果您不想使用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"

编辑:替代方法和解释:

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

apply(df, 1, paste, collapse="")

好的,现在解释一下:

为什么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)

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

答案 1 :(得分:4)

这确实有点奇怪,但这也应该发生。 当您创建data.frame时,列letters将存储为factor。自然因素没有排序,因此当as.numeric()应用于因子时,它返回因子的排序。例如:

> df[, 1]
[1] A B C D E
Levels: A B C D E
> as.numeric(df[, 1])
[1] 1 2 3 4 5

A是因素df[, 1]的第一个级别,因此A在应用1时转换为值as.numeric。这是您致电paste(df[1, ])时发生的情况。由于第1列和第2列属于不同的类,因此首先将第1行的两个元素转换为数字,然后转换为字符。

如果要连接两个列,首先需要将第一行转换为字符:

df[, 1] <- as.character(df[, 1])
paste(df[1,], collapse = "")

正如@ sebastian-c所指出的,你也可以在创建data.frame时使用stringsAsFactors = FALSE,然后你可以省略as.character()步骤。

答案 2 :(得分:3)

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

 new.df<-df%>%
 unite(together, letters, numbers, sep="")

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

答案 3 :(得分:1)

如果你想以

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

..那么关于任何给定函数如何解释df$letters没有一般规则。它是建模函数的一个因素,一些是某些特征,另一些是整数。即使是相同的功能(如粘贴)也可能会有不同的解释,具体取决于您使用它的方式:

paste(df[1,], collapse="") # "11"
apply(df, 1, paste, collapse="") # "A1" "B2" "C3" "D4" "E5"

除了知道每个函数的内部结构后它可能有意义之外,它没有逻辑。

当参数转换为向量时,因子似乎会转换为整数(如您所知,数据帧是相等长度的向量列表,因此数据帧的第一行也是一个列表,当它是被迫成为一个矢量,这样的事情发生了:)

df[1,]
#    letters numbers
# 1       A       1
unlist(df[1,])
# letters numbers 
#  1       1 

我不知道apply如何实现它的功能(即因素由字符值表示) - 如果您有兴趣,请查看其源代码。但是,知道您可以信任(在这个特定意义上)apply(在这个特定场合)可能是有用的。更一般地,以合理的格式存储每条数据是有用的,包括将字符串存储为字符串,即使用stringsAsFactors=FALSE

不过,每本介绍性的R书都应该在副标题中有这个想法。例如,我的退休计划是写一篇“A(不是那么)温和地介绍数据渔业的禅与R,stringsAsFactors = FALSE方式”。