r - 将命名日期列表堆叠到 data.frame
问题描述
我正在做一个用tidyverse
包进行数据清理的学校项目。现在我得到一个purrr::map()
这样的列表输出:
(mylist <- list(A = as.Date(sample(1e3:1e4, 4), origin = "1960-01-01"),
B = as.Date(sample(1e3:1e4, 2), origin = "1960-01-01"),
C = as.Date(sample(1e3:1e4, 3), origin = "1960-01-01")))
$A
[1] "1970-06-12" "1984-05-28" "1967-06-28" "1982-12-14"
$B
[1] "1966-02-04" "1967-02-21"
$C
[1] "1977-07-19" "1968-03-11" "1964-02-13"
我想将它们堆叠到:
df <- data.frame(Value = reduce(mylist, c))
df$Class <- rep(names(mylist), sapply(mylist, length))
df
Value Class
1 1970-06-12 A
2 1984-05-28 A
3 1967-06-28 A
4 1982-12-14 A
5 1966-02-04 B
6 1967-02-21 B
7 1977-07-19 C
8 1968-03-11 C
9 1964-02-13 C
- 注意1:每个单元格的长度不同,列表中的值
Date
实际上是类。 - 注意2:
stack(mylist)
在日期列表中不起作用。
tidyverse
是否有任何方法可以通过函数或其他包中的函数有效地实现它?
解决方案
我们可以用stack
stack(mylist)
# values ind
#1 1 A
#2 2 A
#3 3 A
#4 4 B
#5 5 B
#6 6 B
#7 7 B
#8 8 C
#9 9 C
更新
对于更新的问题,melt
来自reshape2
或data.table
可以使用
library(reshape2)
melt(mylist)
# value L1
#1 3658-09-23 A
#2 2390-06-01 A
#3 2744-01-09 A
#4 2432-02-21 A
#5 4077-11-13 B
#6 4022-11-13 B
#7 3923-11-19 C
#8 2836-08-20 C
#9 3411-01-23 C
或使用tidyverse
library(tidyverse)
enframe(mylist) %>%
unnest
# A tibble: 9 x 2
# name value
# <chr> <date>
#1 A 3658-09-23
#2 A 2390-06-01
#3 A 2744-01-09
#4 A 2432-02-21
#5 B 4077-11-13
#6 B 4022-11-13
#7 C 3923-11-19
#8 C 2836-08-20
#9 C 3411-01-23
基准
以下是使用发布的四种解决方案的一些基准
mylist2 <- rep(mylist, 1e4) #slightly bigger list
system.time({data.table::melt(mylist2)}) #Sotos solution
#user system elapsed
# 3.432 0.025 3.436
system.time({reshape2::melt(mylist2)})
#user system elapsed
# 3.461 0.021 3.472
两个包的melt
功能在性能上只有细微的差别
system.time({rbindlist(lapply(mylist2, as.data.table), idcol = names(mylist2))})
# user system elapsed
# 2.889 0.160 3.029
system.time({enframe(mylist2) %>%
unnest})
# user system elapsed
# 0.149 0.004 0.152
system.time({data.frame(value = reduce(mylist2, c),
class = rep(names(mylist2), lengths(mylist2)))})
# user system elapsed
# 14.714 8.890 23.550
library(microbenchmark)
microbenchmark(
ak1 = reshape2::melt(mylist2),
ak2 = enframe(mylist2) %>%
unnest,
st1 = data.table::melt(mylist2),
st2 = rbindlist(lapply(mylist2, as.data.table), idcol = names(mylist2)),
unit = 'relative', times = 10L)
#Unit: relative
# expr min lq mean median uq max neval cld
# ak1 26.51333 24.38488 21.52345 23.65577 19.36023 18.71291 10 c
# ak2 1.00000 1.00000 1.00000 1.00000 1.00000 1.00000 10 a
# st1 25.34465 24.56934 21.97353 26.27053 19.23078 17.32802 10 c
# st2 16.19268 16.96023 14.28353 16.25288 12.69549 11.58340 10 b
推荐阅读
- java - SSLContextBuilder 无法加载KeyMaterial
- express - 使用 serverless-webpack 部署 express api。续集导入错误
- r - 将 tapply 汇总结果转换为数据框
- android - 没有收到詹金斯电子邮件神器
- android - Android Studio 3.1 Logcat 工具窗口在每一行显示时间戳
- java - @PostMapping 不起作用。HTTP 415 不支持的媒体类型错误
- javascript - 带百分比的随机数
- vba - 在 Excel 图表上切换分组轴
- javascript - 如何为引导开关分配值?
- sonarqube - Sonarqube 服务器 java.lang.OutOfMemoryError:java.util.Arrays.copyOf(Arrays.java:3332) 处的 Java 堆空间