首页 文章

连接数据帧的行

提问于
浏览
25

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

因此,粘贴将行的每个元素转换为一个整数,该整数对应于“相应级别的索引”,就像它是一个因子一样,并且它保持长度为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 回答

  • 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"
    

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

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

    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="")
    

    好的,现在解释一下:

    Why won't as.list work?

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

    Why use 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)
    

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

  • 3

    这确实有点奇怪,但这也应该发生 . 当您创建 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] 的第一个级别,因此当应用 as.numeric 时, A 将转换为值 1 . 当你调用 paste(df[1, ]) 时会发生这种情况 . 由于第1列和第2列属于不同的类,因此首先将第1行的两个元素转换为数字,然后转换为字符 .

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

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

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

  • 0

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

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

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

  • 3

    如果你想开始

    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书都应该在副 Headers 中有这个想法 . 例如,我的退休计划是写“A(不是那么)温和地介绍数据渔业的禅与R,stringsAsFactors = FALSE方式” .

相关问题