【问题标题】:tidy data principles for aggregated data汇总数据的整理数据原则
【发布时间】:2021-07-01 13:27:01
【问题描述】:

我正在尝试处理一些汇总数据。我希望数据采用整洁的格式,但我不确定如何做到这一点而不会得到许多 value 变量。组织这些数据的正确方法是什么?我已经四处寻找,但找不到任何东西。

这是一个例子:

#create the dataframe
df <- data.frame('date' = seq(as.Date('2019-01-15'), as.Date('2019-04-15'), 'months'),
           'total' = c(2, 4, 1, 6),
           'age.0-6' = c(1, 4, 0, 3), 
           'age.7-12' = c(1, 0, 1, 3), 
           'race.white' = c(1, 2, 0, 2), 
           'race.black' = c(1, 2, 1, 2), 
           'race.other' = c(0, 0, 1, 2))  
#print the dataframe
df
        date total age.0_6 age.7_12 race.white race.black race.other
1 2019-01-15     2       1        1          1          1          0
2 2019-02-15     4       4        0          2          2          0
3 2019-03-15     1       0        1          0          1          1
4 2019-04-15     6       3        3          2          2          2

这里的问题是我不知道各个类别,因为数据都是汇总的。例如,对于 2014 年 4 月,我不知道 0-6 岁的比赛是否是:
2 个其他和 1 个白色;或
2个白色和1个黑色;或
1 个黑色、1 个白色和 1 个其他。
因此,我无法获得每个变量的唯一列,每个结果都有一个值。所以我不能用通常的方式整理。

相反,我可以整理年龄和种族,并为每个人设置值列。第一个简单的问题是更改 value 变量的名称,但更大的问题仍然是我有很多变量,每个变量都有一个等价的值。

这是一个简单的例子:

df %>%
  pivot_longer(c(age.0_6, age.7_12), names_to = 'age') %>% #pivot age data
  mutate(age = gsub('[a-z]+\\.', '', age)) %>% #clean the age variable
  pivot_longer(c(race.white, race.black, race.other), names_to = 'race', values_to = 'count') %>% #pivot the race data (use 'count' instead of 'value' 
  mutate(race = gsub('[a-z]+\\.', '', race)) #clean the race data

# A tibble: 24 x 6
   date       total age   value race  count
   <date>     <dbl> <chr> <dbl> <chr> <dbl>
 1 2019-01-15     2 0_6       1 white     1
 2 2019-01-15     2 0_6       1 black     1
 3 2019-01-15     2 0_6       1 other     0
 4 2019-01-15     2 7_12      1 white     1
 5 2019-01-15     2 7_12      1 black     1
 6 2019-01-15     2 7_12      1 other     0
 7 2019-02-15     4 0_6       4 white     2
 8 2019-02-15     4 0_6       4 black     2
 9 2019-02-15     4 0_6       4 other     0
10 2019-02-15     4 7_12      0 white     2
# ... with 14 more rows

这显然不是一个整洁的格式,而且数据非常难以管理。当我拥有大量年龄段、大量种族类别以及许多其他汇总特征:性别、残疾、收入等级等时,这个问题很快就会变得巨大。

对组织此类数据的最佳方式有何想法?我假设它足够普遍并且有最佳实践。

【问题讨论】:

  • 似乎有 14 个人按种族确定,但总共只有 13 个人和年龄。您想如何处理不一致的数据,这大概也可能出现在您的真实数据中?

标签: r tidyverse


【解决方案1】:

我认为您有一些可能有意义的选项,具体取决于您希望如何使用数据。为了可视化数据,我认为将整个事物旋转更长的时间就足够了(下面的#1)。对于每个维度内的分析,将它们保存为单独的表(#2)可能是最安全和最不冒昧的,因为正如您所指出的,维度可以通过多种方式相互关联。如果要一起显示所有维度,则需要对维度之间的关系做出假设。在 #3 中,我假设维度完全不相关,但在实际样本中,这种情况很少发生,并且可能导致错误的结论。 (例如,查看Simpson's Paradox 的示例)


  1. 使维度成为较长表格中的变量

这里我们只是将数据的维度(总数/种族/年龄)设为一列,值设为另一列。

library(tidyverse)
long_all <- df %>% 
  pivot_longer(-date) %>%
  separate(name, c("dimension", "category"), 
           fill = "right", extra = "merge")

如果您想直接进行可视化,这可能是有意义的,您可以按维度过滤或将它们分配给构面:

ggplot(long_all, aes(category, value)) +
  geom_col() +
  facet_wrap(~dimension, scales = "free_x" )

  1. 制作成多个表格

您不知道维度如何相互关联,因此一种干净的方法是保持它们不同。然后,我们可以使用专注于该维度的表格单独分析每个维度。

race <- df %>%
  select(date, contains("race")) %>%
  pivot_longer(-date) %>%
  separate(name, c("dimension", "category"), 
           fill = "right", extra = "merge")

age <- df %>%
  select(date, contains("age")) %>%
  pivot_longer(-date) %>%
  separate(name, c("dimension", "category"), 
           fill = "right", extra = "merge")
  1. 推算假设个人

如果您需要同时包含这两个维度,则必须对它们之间的关系做出假设。例如,您可能会假设样本中的种族和年龄完全相互独立(这可能是一个错误的假设,因此应该注意)。要以这种方式创建假设的交叉表,您可以创建假设的个体,并拥有来自不同年龄和种族的每个样本而无需替换。结果将是原始摘要数据如何出现的一种可能性,但很可能会忽略真实基础数据中存在的模式。

set.seed(42)
shuffle_step <- function(df) {
  df %>%
    uncount(value) %>%
    slice_sample(prop = 1, replace = FALSE) %>%
    group_by(date) %>%
    mutate(row_in_date = row_number()) %>%
    ungroup()
}

imputed_individuals <- full_join(
  age %>%
    shuffle_step %>%
    select(date, row_in_date, age = category),
  race %>%
    shuffle_step %>%
    select(date, row_in_date, race = category),
  by = c("date", "row_in_date"))

在这里,我为每个日期内的每个人创建了一行,并带有一个可能的类别值,无论是种族还是年龄。然后我们将两个结果数据集连接在一起,给出一组可能的个人,他们会产生与我们开始时相同的汇总统计数据,假设维度不相关。

我们在这里看到,被分配种族的人比按年龄或总维度计算的人多一个。他们在列表底部显示NA 年龄。这可能是一个错字,但这种数据错位在现实世界的数据收集中很常见,因此最好考虑到值不一致的可能性。

> imputed_individuals
# A tibble: 14 x 4
   date       row_in_date age   race 
   <date>           <int> <chr> <chr>
 1 2019-02-15           1 0.6   black
 2 2019-04-15           1 0.6   black
 3 2019-01-15           1 0.6   black
 4 2019-04-15           2 7.12  black
 5 2019-04-15           3 0.6   other
 6 2019-02-15           2 0.6   white
 7 2019-04-15           4 7.12  white
 8 2019-04-15           5 0.6   other
 9 2019-01-15           2 7.12  white
10 2019-02-15           3 0.6   white
11 2019-02-15           4 0.6   black
12 2019-03-15           1 7.12  other
13 2019-04-15           6 7.12  white
14 2019-03-15           2 NA    black

我们可以确认这个假设场景与我们的原始数据一致:

long_all %>%
  filter(dimension == "age") %>%
  left_join(
    imputed_individuals %>% count(date, age),
    by = c("date", "category" = "age"))


# A tibble: 8 x 5
  date       dimension category value     n
  <date>     <chr>     <chr>    <dbl> <int>
1 2019-01-15 age       0.6          1     1
2 2019-01-15 age       7.12         1     1
3 2019-02-15 age       0.6          4     4
4 2019-02-15 age       7.12         0    NA
5 2019-03-15 age       0.6          0    NA
6 2019-03-15 age       7.12         1     1
7 2019-04-15 age       0.6          3     3
8 2019-04-15 age       7.12         3     3


long_all %>%
  filter(dimension == "race") %>%
  left_join(
    imputed_individuals %>% count(date, race),
    by = c("date", "category" = "race"))

# A tibble: 12 x 5
   date       dimension category value     n
   <date>     <chr>     <chr>    <dbl> <int>
 1 2019-01-15 race      white        1     1
 2 2019-01-15 race      black        1     1
 3 2019-01-15 race      other        0    NA
 4 2019-02-15 race      white        2     2
 5 2019-02-15 race      black        2     2
 6 2019-02-15 race      other        0    NA
 7 2019-03-15 race      white        0    NA
 8 2019-03-15 race      black        1     1
 9 2019-03-15 race      other        1     1
10 2019-04-15 race      white        2     2
11 2019-04-15 race      black        2     2
12 2019-04-15 race      other        2     2

【讨论】:

  • 感谢乔恩,这非常有帮助。非常感谢您的想法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-27
  • 2017-01-19
相关资源
最近更新 更多