【问题标题】:R: long to wide transformation using reduce and setting suffixesR:使用 reduce 和设置后缀的长到宽转换
【发布时间】:2016-07-01 22:01:00
【问题描述】:

我们以虹膜数据为例,稍作修改:

(注意:使用“UPDATE #1”部分的 4 行代替下面的两行)

data(iris)
iris$id <- rep(1:50, times = 3)

我需要将数据从这种 quazi-long 格式转换为宽格式,以便每一行中的 id 都是相同的。换句话说:原始的iris数据可以看作是一张贴在一张下面的3张表格(每个物种一张)。我需要将这 3 张表粘贴到另一张的一侧。

这很简单,我就是这样做的:

require(purrr)
require(dplyr)
iris %>% split(.$Species) %>% reduce( full_join, by = "id")

上面的示例生成的名称类似于“Petal.Length.x”、...、“Petal.Length.y”、...、“Petal.Length”。我希望它们是:“Petal.Length.setosa”,...,“Petal.Length.versicolor”,...,“Petal.Length.virginica”。所以唯一剩下的就是将物种名称附加到原始变量名称中。

我尝试在reduce 之前使用mapsetNames,但没有成功。

我不想使用 tidyr 的 gatherseparate,因为我的 1.5GB 数据集以纯长格式增长到 13GB(我需要保留很多类似 id 的列)。

我可以使用namesgsub 和一些基本的正则表达式在下一行添加名称,但我很好奇是否可以在不破坏%&gt;% 流程的情况下做到这一点。


更新 #1

谢谢你的回复,lmo!一个非常好的和干净的解决方案!当我第一次看到它时,我觉得我想多了这个问题......但实际上我在stackoverflow上过度简化了它。让我们添加一些混乱:

iris$id <- rep(sample(1:50, 50), times = 3) ## random order
iris$drop_me <- sample(c(1,0), 150, TRUE, c(0.8, 0.2)) ## rows wirh 0 in this column will be missing
iris <- iris[iris$drop_me == 1, ]
iris$drop_me <- NULL

所以我有上面的数据,现在我尝试使用reduce...我也从left_join更新到full_join,因为我意识到我跳过了一些结果。

提前谢谢你和问候。

【问题讨论】:

    标签: r dplyr purrr


    【解决方案1】:

    这是使用splitdo.call 的基本R 方法:

    # get list of data frame, drop the split factor (Species)
    myList <- split(iris[, -which(names(iris) == "Species")], iris$Species)
    # perform wide transformation
    do.call(data.frame, myList)
    

    这会将物种名称放在前面。使用gsub 将它们移到后面并不难。

    这是部分结果:

      setosa.Sepal.Length setosa.Sepal.Width setosa.Petal.Length setosa.Petal.Width
    1                  5.1                3.5                 1.4                0.2
    2                  4.9                3.0                 1.4                0.2
    3                  4.7                3.2                 1.3                0.2
    4                  4.6                3.1                 1.5                0.2
    5                  5.0                3.6                 1.4                0.2
    6                  5.4                3.9                 1.7                0.4
    

    其他物种是附加列。

    更新 #1 的答案

    这有点复杂,虽然第一行是一样的:

    # get list of data frame, drop the split factor (Species)
    myList <- split(iris[, -which(names(iris) == "Species")], iris$Species)
    # add names to data.frames
    myList <- lapply(names(myList),
                     function(i) {
                           setNames(myList[[i]],
                             c(paste0(head(names(myList[[i]]), -1), ".", i), "id"))
                     })
    
    # merge the data.frames together
    Reduce(function(x, y) {merge(x, y, by="id", all=TRUE)}, myList)
    

    这会产生您想要的命名,并将 Species 附加到每个变量的末尾。

    【讨论】:

    • 比你,lmo!一个非常好的和干净的解决方案。不过,我意识到我过于简化了堆栈溢出问题。我更新了问题以正确反映它。问候,rpl。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-20
    • 2010-11-29
    • 2019-08-16
    • 2022-01-20
    相关资源
    最近更新 更多