使用data.frame/tibble展开具有重复标识符的数据

38

tidyr的文档表明gather和spread是可传递的,但使用"iris"数据的以下示例表明它们不是可传递的,但不清楚原因。 如有澄清,将不胜感激。

iris.df = as.data.frame(iris)
long.iris.df = iris.df %>% gather(key = feature.measure, value = size, -Species)
w.iris.df = long.iris.df %>% spread(key = feature.measure, value = size, -Species)

我原以为数据框“w.iris.df”与“iris.df”相同,但实际上收到以下错误信息:

"Error: Duplicate identifiers for rows (1, 2, 3, 4, 5, 6, 7, 8, 9..."

我的一般问题是如何对这种数据集反向应用“gather”。


32
因为没有足够的变量来唯一标识观察结果,所以它不是传递性。尝试添加类似于“iris.df$row <- 1:nrow(iris.df)”这样的内容。 - hadley
2个回答

29

哈德利的介入毫不意外地非常完美......但在那之后,我稍微搞了一下语法......所以,有价值的是,我发布了完全可操作的代码(抱歉,我的语法有点不同于上面的代码):

library(tidyr)
library(dplyr)

wide <- 
  iris %>%
  mutate(row = row_number()) %>%
  gather(vars, val, -Species, -row) %>%
  spread(vars, val)

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

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

它们是相同的......如果你感觉需要,只需重新排序即可......

wide <- wide[,c(3, 4, 5, 6, 1)]  ## Reorder and then remove "row" column

完成了。


0

由于之前的回答可能没有足够清晰,你在执行gather时存在问题,而这个问题会在你尝试执行spread时表现出来。

问题在于,在收集过程中,你失去了对原始数据框中哪一行属于哪个feature.measure的追踪,因此spread无法知道如何将单个值组合成“宽”表格。

iris.df = as.data.frame(iris)
long.iris.df = iris.df %>% 
  tibble::rowid_to_column() %>% 
  gather(key = feature.measure, value = size, -Species, -rowid)

#>   rowid Species feature.measure size
#> 1     1  setosa    Sepal.Length  5.1
#> 2     2  setosa    Sepal.Length  4.9
#> 3     3  setosa    Sepal.Length  4.7
#> 4     4  setosa    Sepal.Length  4.6
#> 5     5  setosa    Sepal.Length  5.0
#> 6     6  setosa    Sepal.Length  5.4

现在,size 中的每个值都保留了其 rowid,因此您始终可以将其重新组合成宽数据集(删除不必要的 rowid):

w.iris.df = long.iris.df %>% 
  spread(key = feature.measure, value = size) %>% 
  select(-rowid)
head(w.iris.df)
#>   Species Petal.Length Petal.Width Sepal.Length Sepal.Width
#> 1  setosa          1.4         0.2          5.1         3.5
#> 2  setosa          1.4         0.2          4.9         3.0
#> 3  setosa          1.3         0.2          4.7         3.2
#> 4  setosa          1.5         0.2          4.6         3.1
#> 5  setosa          1.4         0.2          5.0         3.6
#> 6  setosa          1.7         0.4          5.4         3.9

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接