首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >连接数据框的行

连接数据框的行
EN

Stack Overflow用户
提问于 2012-12-19 09:07:35
回答 4查看 90.7K关注 0票数 43

我想要获取一个包含字符和数字的数据帧,并将每行的所有元素连接成一个字符串,该字符串将作为单个元素存储在一个向量中。例如,我制作了一个由字母和数字组成的数据框,然后我想通过paste函数连接第一行,希望返回值"A1“

代码语言:javascript
运行
复制
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根本没有将df1作为一个因子来存储(通过is.factor()测试,我不能验证它实际上是一个级别的索引)。

代码语言:javascript
运行
复制
is.factor(df[1,])
## [1] FALSE
is.vector(df[1,])
## [1] FALSE

所以如果它不是一个向量,那么它的行为就很奇怪了,但是我不能强迫它变成一个向量

代码语言:javascript
运行
复制
> is.vector(as.vector(df[1,]))
[1] FALSE

在我的尝试中,使用as.character似乎没有帮助

有人能解释这种行为吗?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2012-12-19 09:32:54

当其他人专注于为什么你的代码不能工作以及如何改进它时,我将尝试并更多地专注于获得你想要的结果。从您的描述来看,您似乎可以很容易地使用粘贴来实现您想要的功能:

代码语言:javascript
运行
复制
df <- data.frame(letters = LETTERS[1:5], numbers = 1:5, stringsAsFactors=FALSE)
paste(df$letters, df$numbers, sep=""))

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

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

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

代码语言:javascript
运行
复制
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参数。使用获取每一行并连接它们的想法,下面这行代码将准确地完成您想要的操作:

代码语言:javascript
运行
复制
apply(df, 1, paste, collapse="")

好了,现在来解释一下:

为什么 as.list 不起作用?

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

为什么使用 do.call**?**

do.call允许您使用命名列表作为参数来调用函数。您不能直接将列表放到paste中,因为它不喜欢数据帧。它是为连接向量而设计的。所以请记住,dfargs是一个包含字母向量、数字向量和sep的列表,sep是一个长度为1的向量,只包含"“。当我使用do.call时,产生的粘贴函数本质上是paste(letters, numbers, sep)

但是,如果我的原始数据帧具有列"letters", "numbers", "squigs", "blargs",然后我像以前一样添加分隔符,该怎么办呢?然后,通过do.call的粘贴功能将如下所示:

代码语言:javascript
运行
复制
paste(letters, numbers, squigs, blargs, sep)

所以你可以看到它对任意数量的列都有效。

票数 66
EN

Stack Overflow用户

发布于 2017-05-12 03:04:29

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

代码语言:javascript
运行
复制
 new.df<-df%>%
 unite(together, letters, numbers, sep="")

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

票数 5
EN

Stack Overflow用户

发布于 2012-12-19 09:28:41

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

代码语言:javascript
运行
复制
> 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]的第一个级别,因此在应用as.numeric时,A将转换为值1。这就是调用paste(df[1, ])时发生的事情。由于第1列和第2列属于不同的类,因此paste首先将第1行的两个元素转换为数字,然后转换为字符。

当您想要连接这两列时,首先需要将第一行转换为字符:

代码语言:javascript
运行
复制
df[, 1] <- as.character(df[, 1])
paste(df[1,], collapse = "")

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

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13944078

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档