【问题标题】:How to squeeze multiple observations per person in one row with dplyr?如何使用 dplyr 在一行中挤压每个人的多个观察值?
【发布时间】:2019-10-23 21:52:25
【问题描述】:

我每人有多个观察结果(面板数据)。但实际上对于某种情节,我每人只需要一行,而且我有几个完全没有变化的特征。

这是数据和基本分析:

set.seed(1234)
data = data.frame(id=rep(1:25, each=4), time=seq(1:4),
                  char1 = sample(0:10, 100, replace=T), 
                  char2 = sample(0:5, 100, replace=T),
                  yob = rep(sample(1910:2010, 25, replace=T), each=4))

data <- data %>%
  group_by(yob) %>% # year of birth
  mutate(char1_share = sum(char1==1)/sum(char1)) %>% # first characteristic
  mutate(char2_share = sum(char2==1)/sum(char2))     # second characteristic

ggplot(data = data, aes(x = yob)) + 
  geom_smooth(aes(y=char1_share, color="char1")) + 
  geom_smooth(aes(y=char2_share, color="char2"))

当我使用所有 100 次观察时,我错误地预测了这些关系,因为一个人被多次计算(我的真实数据具有随机数量的人行,例如 1 到 5 次)。我知道如何获取唯一身份的人数:

data %>% distinct(id)

但我不能将它与我的组变异结构结合起来。

数据应按以下方式折叠:

head(data, n=8L)
# A tibble: 8 x 7
# Groups:   yob [2]
     id  time char1 char2   yob char1_share char2_share
  <int> <int> <int> <int> <int>       <dbl>       <dbl>
1     1     1     9     2  1942      0.0222       0.05 
2     1     2     5     3  1942      0.0222       0.05 
3     1     3     4     3  1942      0.0222       0.05 
4     1     4     8     2  1942      0.0222       0.05 
5     2     1     4     1  1970      0.0769       0.143
6     2     2     5     3  1970      0.0769       0.143
7     2     3     3     4  1970      0.0769       0.143
8     2     4     1     1  1970      0.0769       0.143
  • 压缩所有不会因人而异的信息,例如idyob 和共享(char1_sharechar2_share)。它们不会改变。
  • 忘掉对这个特定分析不重要的其他列。那是time。我可以通过 dplyr 中的select 做到这一点。
  • 选择一个人曾经获得的最高价值。所以char1char2 有不同的测量值。对于第 1 个人,它应该等于 9,对于第 2 个人,它应该等于 4,依此类推。

我期待以下小标题:

# A tibble: 8 x 7
# Groups:   yob [2]
     id  char1 char2   yob char1_share char2_share
  <int>  <int> <int> <int>       <dbl>       <dbl>
1     1      9     3  1942      0.0222       0.05 
7     2      5     4  1970      0.0769       0.143

谢谢。

更新:想法我尝试了几个版本的top_nslice。它总是非常接近,例如:

data %>%
  select(-time) %>%
  group_by(id) %>%
  slice(which.max(char1))

在这个版本中,我需要将slice(which.max(char1)) char1 扩展为“逐列”。

【问题讨论】:

    标签: r dplyr


    【解决方案1】:
    data %>% 
      group_by(id) %>% 
      summarise(
        char1 = max(char1),
        char2 = max(char2),
        yob   = yob[[1]],
        char1_share = char1_share[[1]],
        char2_share = char2_share[[1]]
      )
    

    或者,如果它在您的数据上运行得足够快,您可以简单地使用

    data %>% 
      group_by(id) %>% 
      summarise_all(max)
    

    【讨论】:

    • 令人难以置信的快速答案,谢谢你们。 summarise_all 是我要找的,不知道这个动词。
    【解决方案2】:

    这可以在您创建两个共享变量后通过另一个group_bysummarize 来完成。

    data2 <- data %>% 
      group_by(id, yob, char1_share, char2_share) %>%
      summarize(char1 = max(char1),
                char2 = max(char2))
    

    产量:

    head(data2, n = 2)
    # A tibble: 2 x 6
    # Groups:   id, yob, char1_share [2]
         id   yob char1_share char2_share char1 char2
      <int> <int>       <dbl>       <dbl> <int> <int>
    1     1  1942      0.0222       0.05      9     3
    2     2  1970      0.0769       0.143     5     4
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多