使行名不相同的数据变宽

Making data wide where row names are not identical

我正在尝试将模型结果 table 转换为宽格式。由于名称在结果(dv 变量)上不相同,NA 出现在 table 中,我找不到一种方法让每个变量一行。

每个 variable/dv 我需要一行。模型 1 和 3 共享除一个以外的所有变量。

数据:

table <- data.frame(variable=c("intercept", "a", "b", "intercept", "c", "intercept", "a", "e", "intercept", "c"), 
                    b=c(1.2, 0.1, 0.4, 0.3, 0.9, 1.3, 2, .23, .4, .7), 
                    p=(abs(rnorm(10, 0, .3))),
                    model=c(1,1,1,2,2,3,3,3,4,4),
                    dv=c(rep("dv1", 5), rep("dv2", 5)))

> table
            variable    b          p model  dv
        1  intercept 1.20 0.03320481     1 dv1
        2          a 0.10 0.16675234     1 dv1
        3          b 0.40 0.53607394     1 dv1
        4  intercept 0.30 0.14935514     2 dv1
        5          c 0.90 0.58998515     2 dv1
        6  intercept 1.30 0.21040677     3 dv2
        7          a 2.00 0.14183742     3 dv2
        8          e 0.23 0.32034711     3 dv2
        9  intercept 0.40 0.06539247     4 dv2
        10         c 0.70 0.30780133     4 dv2

代码:

table %>% 
  gather(key, value, b, p) %>% unite("stat_var", dv, key, sep=".") %>%
  spread(stat_var, value) %>%
  arrange(model, desc(variable))

输出:

    variable model dv1.b      dv1.p dv2.b      dv2.p
1  intercept     1   1.2 0.21866737    NA         NA
2          b     1   0.4 0.50600799    NA         NA
3          a     1   0.1 0.18751178    NA         NA
4  intercept     2   0.3 0.25133611    NA         NA
5          c     2   0.9 0.04601194    NA         NA
6  intercept     3    NA         NA  1.30 0.34144108
7          e     3    NA         NA  0.23 0.12793927
8          a     3    NA         NA  2.00 0.37614448
9  intercept     4    NA         NA  0.40 0.08852144
10         c     4    NA         NA  0.70 0.26853770

寻找:

正如我在评论中所述,您的预期输出似乎是错误的。

但是,您可以通过调整 model 变量来重现它:

table %>% 
  select(model, everything()) %>% 
  mutate(model=ifelse(model>2, model-2, model)) %>% 
  pivot_longer(c(b, p)) %>% 
  unite("name", c("dv", "name")) %>% 
  pivot_wider()
# # A tibble: 6 x 6
#   model variable  dv1_b   dv1_p dv2_b  dv2_p
#   <dbl> <chr>     <dbl>   <dbl> <dbl>  <dbl>
# 1     1 intercept   1.2  0.193   1.3   0.160
# 2     1 a           0.1  0.650   2     0.476
# 3     1 b           0.4  0.190  NA    NA    
# 4     2 intercept   0.3  0.0435  0.4   0.145
# 5     2 c           0.9  0.372   0.7   0.243
# 6     1 e          NA   NA       0.23  0.297

值得注意的是,gather()spread() 已被弃用,取而代之的是旋转函数,它提供了非常好的改进(尽管此处未使用)。

我将忽略考虑模型之间某种类型的“等效”(使用 mutate() 处理)的原因(我发现没有正当理由)。但只与 table 操作有关,我有这个基本选项来获得你想要的输出:

您可以使用 pivot_wider_spec() 将名称 b 和 p 设置为后缀。

require(tidyverse)

table %>% 
  mutate(model = case_when(model == 3 ~ 1,
                           model == 4 ~ 2,
                           TRUE ~ model)) %>% 
  pivot_wider(names_from = dv, values_from = c("b", "p")) %>% 
  select(variable,
         model,
         ends_with("dv1"),
         ends_with("dv2"))

# A tibble: 6 x 6
# variable  model b_dv1  p_dv1 b_dv2   p_dv2
# <chr>     <dbl> <dbl>  <dbl> <dbl>   <dbl>
#   1 intercept     1   1.2  0.318  1.3   0.200 
# 2 a             1   0.1  0.120  2     0.419 
# 3 b             1   0.4  0.309 NA    NA     
# 4 intercept     2   0.3  0.350  0.4   0.0148
# 5 c             2   0.9  0.185  0.7   0.530 
# 6 e             1  NA   NA      0.23  0.174