如何将分组的行按R中的data.table复制到列中?

时间:2018-07-02 17:44:34

标签: r dataframe dplyr type-conversion

在另一个问题(How to copy grouped rows into column by dplyr/tidyverse in R?)中,我在gather/unite/spread的{​​{1}}的{​​{1}}技术中将行复制到列时遇到内存错误。

这是我用作示例的数据框: (对不起,这个问题中的大多数只是重复先前的问题)

dplyr

我想要的输出如下所示:

R

此操作的图像如下所示: enter image description here

我要在此操作中尝试做的是:

  • 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 转换为列
  • thidtmid中的后缀编号由thid_x定义;但是,tmid_x的最大数量是不可扩展的(在实际的大数据集中,其数量从1扩展到8-10)
  • midmid分组,以定义在每个mid中存储多少hid
  • 如果值不存在,则应用mid填充(即,某些hid具有5个0,而有些只有4个,因此对于此类{ {1}})

但是,当我在上一个问题中使用hid技术执行此操作时,它遇到内存错误,提示无法分配11.4GB内存。

此错误的原因可能是mid函数需要先创建在其参数中指定的所有组合,然后再对其进行拆分。在我的hid 64位版本中,实际数据帧大约有80,000条记录,超过16GB RAM。

您是否有任何建议,可以在不产生如此庞大的中间记录的情况下获得相同的结果?如果gather/unite/spread不需要这种中间操作,也许会有所帮助,但是我曾经使用过gather,但从未使用过该包。 我想让您的想法超越此问题,并根据分析的需要来学习新软件包,以采取进一步的步骤。

1 个答案:

答案 0 :(得分:1)

我认为您可以结合使用spreadleft_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>