1

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

(注意:使用“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”。所以唯一剩下的就是将物种名称附加到原始变量名称中。

我尝试使用mapand setNamesbefore reduce,但没​​有成功。

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

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


更新#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_jointo更新,full_join因为我意识到我正在跳过一些结果。

预先感谢您和问候。

4

1 回答 1

2

这是使用splitand的基本 R 方法do.call

# 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 附加到每个变量的末尾。

于 2016-07-01T22:52:11.690 回答