【问题标题】:Create columns based on count in data.table根据 data.table 中的计数创建列
【发布时间】:2020-02-17 18:12:34
【问题描述】:

我有一个数据如下:

Col1  Col2   Col3  Col4 
1     7000     73     6  
1     7000     73     7   
1     7000     73     8   
1     7000     73     9   
1     7000     73    10   
1     7000     73    11   
1     7000     73    12   
1     4000    117     6 
1     4000    117     9  

我想通过Col1Col2 来数数。然后,根据计数创建 5 个新列。我知道如何计数,但如何根据计数创建 5 个新列。

Col1  Col2   Count   NewCol1  NewCol2  NewCol3  NewCol4  NewCol5  
1     7000       7         6        7        8        9       10  
1     4000       2         6        9        NA      NA       NA  

Col3 其实可以忽略。

有一件事Count的范围从1到大于5。因此,如果Count > 5,我不需要NewCol6NewCol7等。

【问题讨论】:

  • 这是我随机创建的简单示例。在实际数据中,同一Col1Col2下会有5个以上。但是如果超过5个,我就不需要NewCol6...

标签: r data.table data-manipulation


【解决方案1】:

我们用'add_count'创建一个频率列,按'Col1'、'Col2'分组,然后创建一个序列命名列('nm1'),使用complete扩展缺失组合的数据并重塑为'宽'格式与pivot_wider

library(dplyr)
library(tidyr)
library(stringr)
df1 %>%
    add_count(Col1, Col2) %>% 
    group_by(Col1, Col2) %>%
    slice(seq_len(5)) %>%
    mutate(nm1 = str_c("NewCol", row_number())) %>% 
    complete(nm1 = str_c("NewCol", 1:5)) %>%
    ungroup %>% 
    dplyr::select(-Col3) %>% 
    fill(n) %>%
    pivot_wider(names_from = nm1, values_from = Col4)
# A tibble: 2 x 8
#   Col1  Col2     n NewCol1 NewCol2 NewCol3 NewCol4 NewCol5
#  <int> <int> <int>   <int>   <int>   <int>   <int>   <int>
#1     1  4000     1       6      NA      NA      NA      NA
#2     1  7000     2       6       7      NA      NA      NA

使用第二个数据集

df2 %>%
        add_count(Col1, Col2) %>% 
        group_by(Col1, Col2) %>%
        slice(seq_len(5)) %>%
        mutate(nm1 = str_c("NewCol", row_number())) %>% 
        complete(nm1 = str_c("NewCol", 1:5)) %>%
        ungroup %>% 
        dplyr::select(-Col3) %>% 
        fill(n) %>%
        pivot_wider(names_from = nm1, values_from = Col4)
# A tibble: 2 x 8
#   Col1  Col2     n NewCol1 NewCol2 NewCol3 NewCol4 NewCol5
#  <int> <int> <int>   <int>   <int>   <int>   <int>   <int>
#1     1  4000     2       6       9      NA      NA      NA
#2     1  7000     7       6       7       8       9      10

或使用data.table

library(data.table)
dcast(setDT(df2)[, n  := .N, .(Col1, Col2)][,
   head(.SD, 5), .(Col1, Col2)], Col1 + Col2 + n ~  
  factor(paste0("NewCol", rowid(Col1, Col2)), 
       levels = paste0("NewCol", 1:5)), value.var = 'Col4')
#   Col1 Col2 n NewCol1 NewCol2 NewCol3 NewCol4 NewCol5
#1:    1 4000 2       6       9      NA      NA      NA
#2:    1 7000 7       6       7       8       9      10

数据

df1 <- structure(list(Col1 = c(1L, 1L, 1L), Col2 = c(7000L, 7000L, 4000L
), Col3 = c(73L, 73L, 117L), Col4 = c(6L, 7L, 6L)), 
 class = "data.frame", row.names = c(NA, 
-3L))

df2 <- structure(list(Col1 = c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L), 
    Col2 = c(7000L, 7000L, 7000L, 7000L, 7000L, 7000L, 7000L, 
    4000L, 4000L), Col3 = c(73L, 73L, 73L, 73L, 73L, 73L, 73L, 
    117L, 117L), Col4 = c(6L, 7L, 8L, 9L, 10L, 11L, 12L, 6L, 
    9L)), class = "data.frame", row.names = c(NA, -9L))

【讨论】:

  • 我在我的数据上尝试了代码,但它显示NewCol6NewCol7,......而且,它很耗时。
  • unique(dt[, .N, .(Col1, Col2)]$N) &gt;&gt; [1] 1 2 3 4 6 10 5 8 22 7 11 12。最大值为 22.
  • 没有。 Col3 没用。
  • 我更新了示例,使其计数超过 5。
  • @PeterChen 用data.table更新了帖子
【解决方案2】:

另一个data.table 选项:

DT[, as.list(head(c(Col4, rep(NA_real_, 5L)), 5L)), .(Col1, Col2)]

输出:

   Col1 Col2 V1 V2 V3 V4 V5
1:    1 7000  6  7  8  9 10
2:    1 4000  6  9 NA NA NA

数据:

library(data.table)
DT <- fread("Col1  Col2   Col3  Col4 
1     7000     73     6  
1     7000     73     7   
1     7000     73     8   
1     7000     73     9   
1     7000     73    10   
1     7000     73    11   
1     7000     73    12   
1     4000    117     6 
1     4000    117     9")

【讨论】:

    猜你喜欢
    • 2020-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多