【问题标题】:Convert long to wide dataset using data.table::dcast or tidyr使用 data.table::dcast 或 tidyr 将长数据集转换为宽数据集
【发布时间】:2019-07-23 18:36:51
【问题描述】:

给出以下长格式数据。希望对任意数量的时间点执行此操作。

    dat <- structure(list(srdr_id = c("172507", "172507", "172507", "172507", 
"172619", "172619", "172619", "172619"), arm = c("CBT_Educ", 
"CBT_MI", "CBT_Educ", "CBT_MI", "MI", "Educ", "MI", "Educ"), 
    timepoint = c(0, 0, 3, 3, 0, 0, 3, 3), n = c(102, 103, 100, 
    101, 58, 61, 45, 53), mean = c(37.69, 40.23, 34.53, 31.8, 
    4.6, 4.3, 4.4, 4.1), sd = c(16.06, 14.23, 19.78, 19.67, 2.2, 
    2.2, 2.3, 2.5)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-8L))

长数据集:

  srdr_id arm      timepoint     n  mean    sd
  <chr>   <chr>        <dbl> <dbl> <dbl> <dbl>
1 172507  CBT_Educ         0   102  37.7  16.1
2 172507  CBT_MI           0   103  40.2  14.2
3 172507  CBT_Educ         3   100  34.5  19.8
4 172507  CBT_MI           3   101  31.8  19.7
5 172619  MI               0    58   4.6   2.2
6 172619  Educ             0    61   4.3   2.2
7 172619  MI               3    45   4.4   2.3
8 172619  Educ             3    53   4.1   2.5

我想创建一个宽数据集,以便在每个 srdr_id 和 arm 中,三个变量(n、mean 和 sd)出现在同一行中。

  srdr_id arm         n.0  mean.0 sd.0 n.3 mean.3  sd.3

1 172507  CBT_Educ     102  37.7  16.1  100  34.5  19.8
2 172507  CBT_MI       103  40.2  14.2  101  31.8  19.7
5 172619  MI            58   4.6   2.2   45   4.4   2.3
6 172619  Educ          61   4.3   2.2   53   4.1   2.5

以下失败:

is.formula(formula) 中的错误:找不到对象 'srdr_id'

data.table::dcast(data = dat, srdr_id + arm, value.var = c(n_analyzed, mean, sd))

【问题讨论】:

  • 您应该可以将dcastmelt 一起使用:dcast(melt(dat, id.vars = c("arm", "timepoint")), arm ~ variable + timepoint)

标签: r data.table tidyr


【解决方案1】:

此类情况的常见工作流程是收集所有指标,重命名它们,然后再次传播。见下文:

tidyverse:

dat %>%
  gather("measure", "val", n, mean, sd) %>%
  mutate(measure = paste0(measure, ".", timepoint)) %>%
  select(-timepoint) %>%
  spread(measure, val)

# A tibble: 4 x 8
  srdr_id arm      mean.0 mean.3   n.0   n.3  sd.0  sd.3
  <chr>   <chr>     <dbl>  <dbl> <dbl> <dbl> <dbl> <dbl>
1 172507  CBT_Educ   37.7   34.5   102   100  16.1  19.8
2 172507  CBT_MI     40.2   31.8   103   101  14.2  19.7
3 172619  Educ        4.3    4.1    61    53   2.2   2.5
4 172619  MI          4.6    4.4    58    45   2.2   2.3

数据表:

library(data.table)

dt <- as.data.table(dat)

melt(dt, id.vars = c("srdr_id", "arm", "timepoint"))[
  ,`:=`(variable = paste0(variable, ".", timepoint), timepoint = NULL)
  ] %>%
  dcast(srdr_id + arm ~ variable, value.var = "value")

   srdr_id      arm mean.0 mean.3 n.0 n.3  sd.0  sd.3
1:  172507 CBT_Educ  37.69  34.53 102 100 16.06 19.78
2:  172507   CBT_MI  40.23  31.80 103 101 14.23 19.67
3:  172619     Educ   4.30   4.10  61  53  2.20  2.50
4:  172619       MI   4.60   4.40  58  45  2.20  2.30

【讨论】:

  • 优秀。如果我添加一个测量时间点 == 12 的案例,结果是正确的,但列不是时间点顺序。我将如何按顺序生成:mean.0、mean.3、mean.12 等? colnames(wide_tv)[1]“srdr_id”“arm”“mean.0”“mean.12”“mean.3”“n.0”“n.12”“n.3”“sd.0”“sd .12" "sd.3"
  • 对于 tidyverse,您可以在之后添加 select 语句以进行适当的排序。同样,对于data.table,您可以使用setcolorder 函数设置新的列顺序。
【解决方案2】:

另一种选择(可能不是最优雅的)是使用库 dplyr 中的 group_by()summarise()。 在这里,您不必进行一些计算(所有值都已在您的初始数据集中),因此您可以使用 first()last() 等函数来指定您想要的值。

dat %>% 
  group_by(srdr_id, arm) %>% 
  summarise(
    n0 = first(n),     mean0 = first(mean),    sd0 = first(sd), 
    n3 = last(n),      mean3 = last(mean),     sd3 = last(sd)
  )

#   srdr_id arm         n0 mean0   sd0    n3 mean3   sd3
#   <chr>   <chr>    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 172507  CBT_Educ   102  37.7  16.1   100  34.5  19.8
# 2 172507  CBT_MI     103  40.2  14.2   101  31.8  19.7
# 3 172619  Educ        61   4.3   2.2    53   4.1   2.5
# 4 172619  MI          58   4.6   2.2    45   4.4   2.3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-08-11
    • 2016-07-29
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-11
    • 1970-01-01
    相关资源
    最近更新 更多