【问题标题】:Reshape/gather function to create dataset ready for multilevel analysis重塑/收集功能以创建数据集以进行多级分析
【发布时间】:2018-02-07 02:01:03
【问题描述】:

我有一个大数据集,其中 240 个病例代表 240 名患者。他们都接受了神经心理学测试并填写了问卷。此外,他们的重要其他人(以下简称:代理人)也填写了问卷。由于“患者”和“代理”嵌套在“情侣”中,我想在 R 中进行多级分析。为此,我需要重塑我的数据集以运行此类分析。

简单地说,我想“复制”我的行。对于双主题 ID,添加一个包含 1 和 2 的新变量,其中 1 代表患者数据,2 代表代理数据。然后我希望行填充 1. 所有患者数据和包含代理数据的列是 NA 或空或其他,以及 2. 所有代理数据,以及所有患者数据 NA 或空。

假设这是我的数据:

id <- c(1:5)
names <- c('id', 'p1', 'p2', 'p3', 'pr1', 'pr2', 'pr3')
p1 <- c(sample(1:10, 5))
p2 <- c(sample(10:20, 5))
p3 <- c(sample(20:30, 5))
pr1 <- c(sample(1:10, 5))
pr2 <- c(sample(10:20, 5))
pr3 <- c(sample(20:30, 5))

mydf <- as.data.frame(matrix(c(id, p1, p2, p3, pr1, pr2, pr3), nrow = 5))
colnames(mydf) <- names

>mydf

   id p1 p2 p3 pr1 pr2 pr3
1  1  6  20 22 1   10  24
2  2  8  11 24 2   18  29
3  3  7  10 25 6   20  26
4  4  3  14 20 10  15  20
5  5  5  19 29 7   14  22

我希望我的数据最终看起来像这样:

id2 <- rep(c(1:5), each = 2)
names2 <- c('id', 'couple', 'q1', 'q2', 'q3')
couple <- rep(1:2, 5)
p1 <- c(sample(1:10, 5))
p2 <- c(sample(10:20, 5))
p3 <- c(sample(20:30, 5))
pr1 <- c(sample(1:10, 5))
pr2 <- c(sample(10:20, 5))
pr3 <- c(sample(20:30, 5))

mydf <- as.data.frame(matrix(c(id2, couple, p1, p2, p3, pr1, pr2, pr3), nrow = 10, ncol = 5))
colnames(mydf) <- names2

>mydf
   id couple q1 q2 q3
1   1      1  6 23 16
2   1      2 10 28 10
3   2      1  1 27 14
4   2      2  7 21 20
5   3      1  5 30 18
6   3      2 12  2 27
7   4      1 10  1 25
8   4      2 13  7 21
9   5      1 11  6 20
10  5      2 18  3 23

或者,如果这是不可能的,像这样:

   id couple bb1 bb2 bb3 pbb1 pbb2 pbb3
1   1      1  6  23  16
2   1      2             10   28   10
3   2      1  1  27  14
4   2      2             7    21   20
5   3      1  5  30  18
6   3      2             12   2    27
7   4      1 10   1  25
8   4      2             13   7    21
9   5      1 11   6  20
10  5      2             18   3    23

现在,为了让我到达那里,我已经尝试了 melt() 函数和 gather() 函数,感觉就像我很接近但它仍然没有按照我想要的方式工作。

注意,在我的数据集中,患者问卷的变量名称是 bb1:bb54,代理问卷的变量名称是 pbb1:pbb54

我尝试过的示例

df_long <- df_reshape %>%
gather(testname, value, -(bb1:bb11), -(pbb1:pbb11), -id, -pgebdat, -p_age, na.rm=T) %>%
arrange(id)

【问题讨论】:

    标签: r reshape melt multi-level multilevel-analysis


    【解决方案1】:

    一种方法是在tidyr 中使用uniteseparate,以及gather 函数。

    我正在使用您的 mydf 数据框,因为它已提供,但进行任何更改应该非常简单:

    mydf %>% 
      unite(p1:p3, col = `1`, sep = ";") %>% # Combine responses of 'p1' through 'p3'
      unite(pr1:pr3, col = `2`, sep = ";") %>% # Combine responses of 'pr1' through 'pr3'
      gather(couple, value, `1`:`2`) %>% # Form into long data
      separate(value, sep = ";", into = c("q1", "q2", "q3"), convert = TRUE) %>% # Separate and retrieve original answers
      arrange(id)
    

    这给了你:

       id couple q1 q2 q3
    1   1      1  9 18 25
    2   1      2 10 18 30
    3   2      1  1 11 29
    4   2      2  2 15 29
    5   3      1 10 19 26
    6   3      2  3 19 25
    7   4      1  7 10 23
    8   4      2  1 20 28
    9   5      1  6 16 21
    10  5      2  5 12 26
    

    我们的数字不同,因为它们都是用sample 随机生成的。


    根据@alistaire 评论编辑:将convert = TRUE 添加到separate 调用以确保响应仍然是整数类。

    【讨论】:

    • 我在我的数据集的一个小子集上进行了这项工作,其中我还包括了诸如出生日期和他们接受治疗的医院之类的变量。你知道是否可以在这篇文章中写一些东西代码以便这些值不会“重复”?现在,对于代理而言,它会收到与患者相同的出生日期。
    • 嗯,上面的内容应该足够灵活,可以处理额外的列。您可能需要提供您的工作数据框样本(填充虚拟数据),以便我复制并更好地理解问题。
    • 小心,除了id 之外,您已经使用unite 将所有内容都变成了字符串。您可以通过将convert = TRUE 添加到gatherseparate 调用来解决此问题。
    • 很好的电话!和我的明确监督。我现在已编辑以包含此内容。
    【解决方案2】:

    如果我正确理解您想要的内容,您可以将所有内容收集成一个很长的形式,然后重新整形为稍宽的形式:

    library(tidyverse)
    set.seed(47)    # for reproducibility
    
    mydf <- data.frame(id = c(1:5),
                       p1 = c(sample(1:10, 5)),
                       p2 = c(sample(10:20, 5)),
                       p3 = c(sample(20:30, 5)),
                       pr1 = c(sample(1:10, 5)),
                       pr2 = c(sample(10:20, 5)),
                       pr3 = c(sample(20:30, 5)))
    
    mydf_long <- mydf %>% 
        gather(var, val, -id) %>% 
        separate(var, c('couple', 'q'), -2) %>% 
        mutate(q = paste0('q', q)) %>% 
        spread(q, val)
    
    mydf_long
    #>    id couple q1 q2 q3
    #> 1   1      p 10 17 21
    #> 2   1     pr 10 11 24
    #> 3   2      p  4 13 27
    #> 4   2     pr  4 15 20
    #> 5   3      p  7 14 30
    #> 6   3     pr  1 14 29
    #> 7   4      p  6 18 24
    #> 8   4     pr  8 20 30
    #> 9   5      p  9 16 23
    #> 10  5     pr  3 18 25
    

    【讨论】:

      猜你喜欢
      • 2018-02-08
      • 1970-01-01
      • 2020-04-16
      • 2017-11-08
      • 2022-10-13
      • 2020-12-11
      • 1970-01-01
      • 2012-12-16
      • 1970-01-01
      相关资源
      最近更新 更多