在另一个问题(How to copy grouped rows into column by dplyr/tidyverse in R?)中,我在gather/unite/spread
的{{1}}的{{1}}技术中将行复制到列时遇到内存错误。
这是我用作示例的数据框: (对不起,这个问题中的大多数只是重复先前的问题)
dplyr
我想要的输出如下所示:
R
我要在此操作中尝试做的是:
df <- data.frame(
hid=c(1,1,1,1,2,2,2,2,2,3,3,3,3),
mid=c(1,2,3,4,1,2,3,4,5,1,2,3,4),
tmid=c("010","01010","010","01020",
"010","0120","010","010","020",
"010","01010","010","01020"),
thid=c("010","02020","010","02020",
"000","0120","010","010","010",
"010","02020","010","02020")
)
和 hid mid tmid thid tmid_1 tmid_2 tmid_3 tmid_4 tmid_5 thid_1 thid_2 thid_3 thid_4 thid_5
* <dbl> <dbl> <fctr> <fctr> <fctr> <fctr> <fctr> <fctr> <fctr> <fctr> <fctr> <fctr> <fctr> <fctr>
1 1 1 010 010 010 01010 010 01020 0 010 02020 010 02020 0
2 1 2 01010 02020 010 01010 010 01020 0 010 02020 010 02020 0
3 1 3 010 010 010 01010 010 01020 0 010 02020 010 02020 0
4 1 4 01020 02020 010 01010 010 01020 0 010 02020 010 02020 0
5 2 1 010 000 010 0120 010 010 020 000 0120 010 010 010
6 2 2 0120 0120 010 0120 010 010 020 000 0120 010 010 010
7 2 3 010 010 010 0120 010 010 020 000 0120 010 010 010
8 2 4 010 010 010 0120 010 010 020 000 0120 010 010 010
9 2 5 020 010 010 0120 010 010 020 000 0120 010 010 010
10 3 1 010 010 010 01010 010 01020 0 010 02020 010 02020 0
11 3 2 01010 02020 010 01010 010 01020 0 010 02020 010 02020 0
12 3 3 010 010 010 01010 010 01020 0 010 02020 010 02020 0
13 3 4 01020 02020 010 01010 010 01020 0 010 02020 010 02020 0
转换为列thid
和tmid
中的后缀编号由thid_x
定义;但是,tmid_x
的最大数量是不可扩展的(在实际的大数据集中,其数量从1扩展到8-10)mid
按mid
分组,以定义在每个mid
中存储多少hid
mid
填充(即,某些hid
具有5个0
,而有些只有4个,因此对于此类{ {1}})但是,当我在上一个问题中使用hid
技术执行此操作时,它遇到内存错误,提示无法分配11.4GB内存。
此错误的原因可能是mid
函数需要先创建在其参数中指定的所有组合,然后再对其进行拆分。在我的hid
64位版本中,实际数据帧大约有80,000条记录,超过16GB RAM。
您是否有任何建议,可以在不产生如此庞大的中间记录的情况下获得相同的结果?如果gather/unite/spread
不需要这种中间操作,也许会有所帮助,但是我曾经使用过gather
,但从未使用过该包。
我想让您的想法超越此问题,并根据分析的需要来学习新软件包,以采取进一步的步骤。
答案 0 :(得分:1)
我认为您可以结合使用spread
和left_join
来获得所需的内容:
library(dplyr)
library(tidyr)
a <- select(df, -thid) %>%
spread(mid, tmid, sep="_") %>%
rename_at(vars(matches("^mid_")), funs(paste0("t", .)))
b <- select(df, -tmid) %>%
spread(mid, thid, sep="_") %>%
rename_at(vars(matches("^mid_")), funs(gsub("^m", "th", .)))
left_join(df, a, by="hid") %>%
left_join(b, by="hid")
# hid mid tmid thid tmid_1 tmid_2 tmid_3 tmid_4 tmid_5 thid_1 thid_2 thid_3 thid_4 thid_5
# 1 1 1 010 010 010 01010 010 01020 <NA> 010 02020 010 02020 <NA>
# 2 1 2 01010 02020 010 01010 010 01020 <NA> 010 02020 010 02020 <NA>
# 3 1 3 010 010 010 01010 010 01020 <NA> 010 02020 010 02020 <NA>
# 4 1 4 01020 02020 010 01010 010 01020 <NA> 010 02020 010 02020 <NA>
# 5 2 1 010 000 010 0120 010 010 020 000 0120 010 010 010
# 6 2 2 0120 0120 010 0120 010 010 020 000 0120 010 010 010
# 7 2 3 010 010 010 0120 010 010 020 000 0120 010 010 010
# 8 2 4 010 010 010 0120 010 010 020 000 0120 010 010 010
# 9 2 5 020 010 010 0120 010 010 020 000 0120 010 010 010
# 10 3 1 010 010 010 01010 010 01020 <NA> 010 02020 010 02020 <NA>
# 11 3 2 01010 02020 010 01010 010 01020 <NA> 010 02020 010 02020 <NA>
# 12 3 3 010 010 010 01010 010 01020 <NA> 010 02020 010 02020 <NA>
# 13 3 4 01020 02020 010 01010 010 01020 <NA> 010 02020 010 02020 <NA>
清理NA
值应该很容易,但是可能需要您重构它们(添加级别"0"
)或仅使用stringsAsFactors=FALSE
创建框架。 / p>