【问题标题】:Format nested data.frame grouped by ids using tidyverse使用 tidyverse 格式化按 id 分组的嵌套 data.frame
【发布时间】:2020-07-31 23:22:05
【问题描述】:

我有一个嵌套数据集,每行有两个 id,如下所示:

df <- data.frame(
        sample = rep(paste0("s", 1:5), each = 5),
        ID1 = paste0("id1.", 1:5),
        ID2 = paste0("id2.", 1:5),
        counts = rep(1:5, each = 5)) %>%
    arrange(ID1) %>%
    group_by(ID1, ID2) %>% nest

我想获得一个数据框以进行进一步分析,第一行给出样本,接下来的列给出计数(每个 id),合并的 id 作为列名:

df3 <- data.frame(
    sample = paste0("s", 1:5),
    "id1.1|id2.1" = 1:5,
    "id1.2|id2.2" = 1:5,
    "id1.3|id2.3" = 1:5,
    "id1.4|id2.4" = 1:5,
    "id1.5|id2.5" = 1:5)

我已经开始格式化了:

df2 <- df %>% 
    mutate(sample = data %>% map(pull, sample)) %>%
    mutate(counts = data %>% map(pull, counts))

但是我不确定继续使用哪种优雅的方法。

【问题讨论】:

  • 感谢您的回复 - 我的代码中似乎有错误...我正在检查!
  • 我改变了我的例子。给您带来的不便敬请谅解!

标签: r tidyverse


【解决方案1】:

tidyr 解决方案,取消嵌套列,然后转为宽格式。

library(tidyr)

df %>%
  unite(ID, ID1, ID2) %>%
  unnest(data) %>%
  pivot_wider(names_from = ID, values_from = counts)

# # A tibble: 5 x 6
#   sample id1.1_id2.1 id1.2_id2.2 id1.3_id2.3 id1.4_id2.4 id1.5_id2.5
#   <chr>        <int>       <int>       <int>       <int>       <int>
# 1 s1               1           1           1           1           1
# 2 s2               2           2           2           2           2
# 3 s3               3           3           3           3           3
# 4 s4               4           4           4           4           4
# 5 s5               5           5           5           5           5

或者从你的工作开始

df %>% 
  ungroup() %>% 
  mutate(sample = data %>% map("sample"),
         counts = data %>% map("counts"), .keep = "unused") %>% 
  unite(ID, ID1, ID2) %>%
  unnest(-ID) %>%
  pivot_wider(names_from = ID, values_from = counts)

注意mutate(sample = data %&gt;% map("sample")mutate(sample = data %&gt;% map(pull, sample))的快捷方式,是map()的一个特性。

【讨论】:

  • 还有一个问题:我在df2上做了一些计算,想从这个data.frame开始。你能告诉我如何调整你的代码吗?
  • 确切地说:用df2得到df3。
【解决方案2】:

我们可以通过粘贴“ID1”、“ID2”来创建“ID”列,并使用pivot_wider 转换为更宽的格式

library(dplyr)
library(purrr)
library(tidyr)
library(stringr)
df %>% 
     ungroup %>% 
     unnest %>% 
     transmute(ID = str_c(ID1, ID2, sep="_"), sample, counts) %>%
     pivot_wider(names_from = ID, values_from = counts)
# A tibble: 5 x 6
#  sample id1.1_id2.1 id1.2_id2.2 id1.3_id2.3 id1.4_id2.4 id1.5_id2.5
#  <chr>        <int>       <int>       <int>       <int>       <int>
#1 s1               1           1           1           1           1
#2 s2               2           2           2           2           2
#3 s3               3           3           3           3           3
#4 s4               4           4           4           4           4
#5 s5               5           5           5           5           5

如果“数据”中有多个列并且想要对某些列进行子集化

df %>%
   ungroup %>% 
   mutate(data = map(data, select, c(sample, counts))) %>%
   unnest %>% 
   transmute(ID = str_c(ID1, ID2, sep="_"), sample, counts) %>%
   pivot_wider(names_from = ID, values_from = counts)

或者与dcast在一行中

dcast(setDT(unnest(df)), sample ~ paste(ID1, ID2, sep="_"), values.var = 'counts')
#    sample id1.1_id2.1 id1.2_id2.2 id1.3_id2.3 id1.4_id2.4 id1.5_id2.5
#1:     s1           1           1           1           1           1
#2:     s2           2           2           2           2           2
#3:     s3           3           3           3           3           3
#4:     s4           4           4           4           4           4
#5:     s5           5           5           5           5           5

【讨论】:

    猜你喜欢
    • 2021-04-25
    • 2013-02-02
    • 2019-02-26
    • 1970-01-01
    • 2020-09-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多