如何将长数据汇总为新的宽格式变量并在 R 中保留重要的组信息

How to summarise long data into new wide format variables and keep improtant group information in R

抱歉,如果这个问题得到了回答,我确实查看了其他已发布的问题,这些问题帮助我到达了现在的位置,但现在正在苦苦挣扎,我是 R/ 计算机的新手,任何帮助将不胜感激!

我有一个数据集,其中每一行代表一个主题。数据集非常“广泛”,大约有 200 个变量(列)。我还有一个“长”数据集,其中包含对从每个受试者收集的样本进行的实验室测试结果。我已经合并了这些数据集,这样现在每个主题都可以出现多次,即有多个行,具体取决于收到和测试的实验室样本数量。

我现在想尝试分析为每个主题发送了多少个样本类型的样本。下面是一个简化的例子,希望有助于解释。

#example data frame
sample_type <- c("blood", "blood", "sputum", "blood", "csf", "blood", "csf", "sputum", "sputum", "sputum", "sputum", "blood", "csf", "csf")
id <- c(1,1,1,2,3,4,4,5,5,5,6,6,7,7)
example_data <- data.frame(id, sample_type)

   id sample_type
1   1       blood
2   1       blood
3   1      sputum
4   2       blood
5   3         csf
6   4       blood
7   4         csf
8   5      sputum
9   5      sputum
10  5      sputum
11  6      sputum
12  6       blood
etc.

这里我尝试创建新的变量。如果我在末尾省略“distict”函数,这就可以正常工作,但是当 distict 函数折叠输出时,它似乎 select 只有一个 sample_type 然后省略其他列中的数据

example_data %>% 
  add_count(id, sample_type, name = "test_freq") %>% 
  mutate(blood_freq = case_when(sample_type == "blood" ~ test_freq),
         sputum_freq = case_when(sample_type == "sputum" ~ test_freq),
         csf_freq = case_when(sample_type == "csf" ~ test_freq)) %>% 
  distinct(id, .keep_all = 
             T)

没有distict功能,patient(id)号。例如 1 在 blood_freq 列中有 2 个,在 sputum_freq 列中有一个

   id sample_type test_freq blood_freq sputum_freq csf_freq
1   1       blood         2          2          NA       NA
2   1       blood         2          2          NA       NA
3   1      sputum         1         NA           1       NA
4   2       blood         1          1          NA       NA
5   3         csf         1         NA          NA        1
6   4       blood         1          1          NA       NA

添加了 distict 函数后,blood_freq 是正确的,但 sputum_freq 现在是 NA

  id sample_type test_freq blood_freq sputum_freq csf_freq
1  1       blood         2          2          NA       NA
2  2       blood         1          1          NA       NA
3  3         csf         1         NA          NA        1
4  4       blood         1          1          NA       NA

下面是我得到的最接近的结果,但是输出有点奇怪,因为“test_freq”列中的值不是唯一的。我还担心,如果我开始旋转更长时间,我将不得不在许多其他列中定义我想用我的其余数据做什么?但也许这不是我应该担心的事情?

example_data %>% 
  add_count(id, sample_type, name = "test_freq")  %>% 
  pivot_wider(names_from = sample_type, values_from = test_freq) %>% 
  distinct(id, .keep_all = TRUE)

     id blood     sputum    csf      
  <dbl> <list>    <list>    <list>   
1     1 <int [2]> <int [1]> <NULL>   
2     2 <int [1]> <NULL>    <NULL>   
3     3 <NULL>    <NULL>    <int [1]>
4     4 <int [1]> <NULL>    <int [1]>
5     5 <NULL>    <int [3]> <NULL>   
6     6 <int [1]> <int [1]> <NULL>   
7     7 <NULL>    <NULL>    <int [2]>

最后我想说的是,x 位受试者发送了 y 次痰液测试,x 位受试者进行了 y 次血液和 z 次痰液测试等

我发现此代码很好地概述了已发送的测试,但不允许我查看例如有多少患者有一份血液和一份痰,因此我尝试将这些示例中所示的数据转换为更好地分析它,但不能完全到达那里!

> example_data %>% group_by(id) %>% count(sample_type) %$% table(sample_type,n)
           n
sample_type 1 2 3
     blood  3 1 0
     csf    2 1 0
     sputum 2 0 1

我希望这是有道理的?我愿意接受所有建议,甚至是任何其他以更好的方式实现这一目标的想法。

非常感谢!!

也许是这样的?

我将计算每个 id-sample_type 的数据的一个版本与仅计算每个 id 的数据的另一个版本(此版本称为“测试”)绑定。然后我们可以旋转组合数据集以提供示例的摘要列。

library(tidyverse)
bind_rows(
  example_data %>% count(id, sample_type),
  example_data %>% count(id) %>%
    mutate(sample_type = "test")) %>%
  pivot_wider(names_from = sample_type, values_from = n, 
              names_glue = "{sample_type}_freq")

结果

# A tibble: 7 x 5
     id blood_freq sputum_freq csf_freq test_freq
  <dbl>      <int>       <int>    <int>     <int>
1     1          2           1       NA         3
2     2          1          NA       NA         1
3     3         NA          NA        1         1
4     4          1          NA        1         2
5     5         NA           3       NA         3
6     6          1           1       NA         2
7     7         NA          NA        2         2

对于你问题的后半部分,你写“最后我想说的是,x 很多受试者发送了 y 次痰液测试,并且 x 很多人有 y 次血液和 z 次痰液等."

你可以这样做:

example_data %>% 
  count(id, sample_type) %>%
  count(sample_type, n)

结果

Storing counts in `nn`, as `n` already present in input
ℹ Use `name = "new_name"` to pick a new name.
  sample_type n nn
1       blood 1  3
2       blood 2  1
3         csf 1  2
4         csf 2  1
5      sputum 1  2
6      sputum 3  1

这告诉我们 3 个 id 进行了 1 次血液检查,1 个 id 进行了 2 次血液检查,2 个 id 进行了 1 次 csf 测试,等等。

或者如果我们对血液和痰液检测的组合感兴趣:

example_data %>% 
  count(id, sample_type) %>%
  pivot_wider(names_from = sample_type, values_from = n) %>%
  count(blood, sputum)

结果

# A tibble: 5 x 3
  blood sputum     n
  <int>  <int> <int>
1     1      1     1
2     1     NA     2
3     2      1     1
4    NA      3     1
5    NA     NA     2

这告诉我们只有一个 id 有 2 个血液和 1 个痰测试,但 2 个有 1 个测试但没有痰。 (顺便说一句,如果你想用 0 替换 NA,你可以将 values_fill = 0 添加到 pivot_wider。)