R:使用reduce和设置后缀进行长到大的转换

时间:2016-07-01 22:01:00

标签: r dplyr purrr

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

(注意:而不是以下两行使用来自" UPDATE#1"部分的4行

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

我需要将这种quazi-long格式的数据转换为宽格式,以便在每一行中id都相同。换句话说:原始虹膜数据可以被视为3个表(每个物种一个)粘贴在另一个之下。我需要将这3个表格粘贴在另一个表格的旁边。

这很简单,我这样做了:

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

以上示例生成名称,如&#34; Petal.Length.x&#34;,...,&#34; Petal.Length.y&#34;,...,&#34; Petal.Length& #34 ;.我更喜欢他们:&#34; Petal.Length.setosa&#34;,...,&#34; Petal.Length.versicolor&#34;,...,&#34; Petal。 Length.virginica&#34 ;.因此,唯一剩下的就是将物种名称附加到原始变量名称。

我尝试在map之前使用setNamesreduce,但没有成功。

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

我可以使用namesgsub和一些基本的正则表达式在下一行添加名称,但我很好奇是否可以在不打破%>%流量的情况下进行。< / p>

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

提前感谢您的问候。

1 个答案:

答案 0 :(得分:2)

以下是使用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。