让我们以虹膜数据为例,稍加修改:
(注意:而不是以下两行使用来自" 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
之前使用setNames
和reduce
,但没有成功。
我不想使用tidyr的gather
和separate
,因为我的1.5GB数据集以纯长格式增长到13GB(我有很多id-像我需要保留的列。)
我可以使用names
,gsub
和一些基本的正则表达式在下一行添加名称,但我很好奇是否可以在不打破%>%
流量的情况下进行。< / 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
,因为我意识到我正在跳过一些结果。
提前感谢您的问候。
答案 0 :(得分:2)
以下是使用split
和do.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。