【问题标题】:How to include missing data points in r如何在 r 中包含缺失的数据点
【发布时间】:2021-05-02 18:56:30
【问题描述】:

这个问题是我上一篇文章 (How to calculate moving average for two years in r) 的衍生问题。

我有一个关于并购 (M&A) 的大数据框(90 万行)。

df 有四列:date(并购完成时间)、target_nation(合并/收购的国家/地区的公司)、acquiror_nation(收购方是哪个国家的公司)和 big_corp_TF(收购方是否是大公司,其中 TRUE 表示公司是大公司)。这是我的数据示例:

> df <- structure(list(date = c(2000L, 2000L, 2001L, 2001L, 2001L, 2002L, 
    2002L, 2002L, 2003L, 2003L, 2004L, 2004L, 2004L, 2006L, 2006L
    ), target_nation = c("Uganda", "Uganda", "Uganda", "Uganda", 
    "Uganda", "Uganda", "Uganda", "Uganda", "Uganda", "Uganda", "Uganda", 
    "Uganda", "Uganda", "Uganda", "Uganda"), acquiror_nation = c("France", 
    "Germany", "France", "France", "Germany", "France", "France", 
    "Germany", "Germany", "Germany", "France", "France", "Germany", 
    "France", "France"), big_corp_TF = c(TRUE, FALSE, TRUE, FALSE, FALSE, 
    TRUE, TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, TRUE, TRUE, TRUE)), row.names = c(NA, 
    -15L))

> df
    
        date target_nation acquiror_nation big_corp_TF
     1: 2000        Uganda          France     TRUE
     2: 2000        Uganda         Germany    FALSE
     3: 2001        Uganda          France     TRUE
     4: 2001        Uganda          France    FALSE
     5: 2001        Uganda         Germany    FALSE
     6: 2002        Uganda          France     TRUE
     7: 2002        Uganda          France     TRUE
     8: 2002        Uganda         Germany     TRUE
     9: 2003        Uganda         Germany     TRUE
    10: 2003        Uganda         Germany    FALSE
    11: 2004        Uganda          France     TRUE
    12: 2004        Uganda          France    FALSE
    13: 2004        Uganda         Germany     TRUE
    14: 2006        Uganda          France     TRUE
    15: 2006        Uganda          France     TRUE

注意: 2003 年法国没有行;并且没有 2005 年。

根据这些数据,我想创建一个新变量来表示特定收购国的大公司进行的并购份额,计算 2 年的平均值。(在我的实际练习中,我将计算 5 年的平均值,但让我们在这里保持简单)。所以法国大公司会有一个新变量,德国大公司会有一个新变量。

有人建议我使用以下代码:

library(runner)
library(tidyverse)
df <- df %>% as.data.frame()
param <- 'France'
df %>% 
  group_by(date, target_nation) %>%
  mutate(n1 = n()) %>%
  group_by(date, target_nation, acquiror_nation) %>%
  summarise(n1 = mean(n1),
            n2 = sum(big_corp_TF), .groups = 'drop') %>%
  filter(acquiror_nation == param) %>%
  mutate(share = sum_run(n2, k=2)/sum_run(n1, k=2))

哪个输出这个小标题:

   date target_nation acquiror_nation    n1    n2 share
  <int> <chr>         <chr>           <dbl> <int> <dbl>
1  2000 Uganda        France              2     1   0.5
2  2001 Uganda        France              3     1   0.4
3  2002 Uganda        France              3     2   0.5
4  2004 Uganda        France              3     1   0.5
5  2006 Uganda        France              2     2   0.6

注意:法国没有 2003 年和 2005 年的结果;我希望有 2003 年和 2005 年的结果(因为我们正在计算 2 年的平均值,因此我们应该能够获得 2003 年和 2005 年的结果)。另外,2006 年的份额实际上是不正确的,因为它应该是 1(应该取 2005 年的值(即 0)而不是 2004 年的值来计算平均值)。

我希望能够收到以下 tibble:

       date target_nation acquiror_nation    n1    n2 share
      <int> <chr>         <chr>           <dbl> <int> <dbl>
    1  2000 Uganda        France              2     1   0.5
    2  2001 Uganda        France              3     1   0.4
    3  2002 Uganda        France              3     2   0.5
    4  2003 Uganda        France              2     0   0.4
    5  2004 Uganda        France              3     1   0.2
    6  2005 Uganda        France              0     0   0.33
    7  2006 Uganda        France              2     2   1.0

注意:请注意,2006 年的结果也有所不同(因为我们现在将 2005 年而不是 2004 年作为两年平均值)。

我知道这是原始数据的问题:它只是缺少某些数据点。但是,将它们包含在原始数据集中似乎非常不方便;中途包含它们可能会更好,例如在计算 n1 和 n2 之后。但是最方便的方法是什么?

非常感谢任何建议。

【问题讨论】:

    标签: r missing-data moving-average


    【解决方案1】:

    使用tidyr::complete 及其参数nestingfill。可以使用的完整代码。

    param <- 'France'
    
    df %>% 
      mutate(d = 1) %>%
      complete(date = seq(min(date), max(date), 1), nesting(target_nation, acquiror_nation),
               fill = list(d =0, big_corp_TF = FALSE)) %>%
      group_by(date, target_nation) %>%
      mutate(n1 = sum(d)) %>%
      group_by(date, target_nation, acquiror_nation) %>%
      summarise(n1 = mean(n1),
                n2 = sum(big_corp_TF), .groups = 'drop') %>%
      filter(acquiror_nation == param) %>%
      mutate(share = sum_run(n2, k=2)/sum_run(n1, k=2))
    
    # A tibble: 7 x 6
       date target_nation acquiror_nation    n1    n2 share
      <dbl> <chr>         <chr>           <dbl> <int> <dbl>
    1  2000 Uganda        France              2     1 0.5  
    2  2001 Uganda        France              3     1 0.4  
    3  2002 Uganda        France              3     2 0.5  
    4  2003 Uganda        France              2     0 0.4  
    5  2004 Uganda        France              3     1 0.2  
    6  2005 Uganda        France              0     0 0.333
    7  2006 Uganda        France              2     2 1
    

    【讨论】:

      【解决方案2】:
      df2 = df %>% 
        group_by(date, target_nation) %>%
        mutate(n1 = n()) %>%
        group_by(date, target_nation, acquiror_nation) %>%
        summarise(n1 = mean(n1),
                  n2 = sum(big_corp_TF), .groups = 'drop') %>%
        filter(acquiror_nation == param)
      
      dates = seq(min(df2$date), max(df2$date), by = 1)
      dates = setdiff(dates, df2$date)
      df3 = df2[rep(nrow(df2), each = length(dates)), ]
      df3$n1 = 0; df3$n2 = 0; df3$date = dates
      
      df2 = arrange(rbind(df2,df3), date)
      df2 = df2 %>% mutate(share = sum_run(n2, k=2)/sum_run(n1, k=2))
      df2
      # A tibble: 7 x 6
         date target_nation acquiror_nation    n1    n2 share
        <dbl> <fct>         <fct>           <dbl> <dbl> <dbl>
      1  2000 Uganda        France              2     1 0.5  
      2  2001 Uganda        France              3     1 0.4  
      3  2002 Uganda        France              3     2 0.5  
      4  2003 Uganda        France              0     0 0.667
      5  2004 Uganda        France              3     1 0.333
      6  2005 Uganda        France              0     0 0.333
      7  2006 Uganda        France              2     2 1    
      

      说明

      首先,根据您的df 创建df2,但不计算share。创建从最小值到最大值的日期序列:

      dates = seq(min(df2$date), max(df2$date), by = 1)
      

      只留下df2中缺少的那些:

      dates = setdiff(dates, df2$date)
      

      为每个缺失的日期创建一行并将n1n2 设置为0:

      df3 = df2[rep(nrow(df2), each = length(dates)), ]
      df3$n1 = 0; df3$n2 = 0; df3$date = dates
      

      合并行并按日期排序:

      df2 = arrange(rbind(df2,df3), date)
      

      最后计算share

      df2 = df2 %>% mutate(share = sum_run(n2, k=2)/sum_run(n1, k=2))
      

      抱歉,这不符合 tidyverse 语法

      【讨论】:

      • 谢谢,@VitaminB16。然而,代码有一个问题:它不应该总是将 0 分配给 n1。 2003 年有 2 行(只是法国在 2003 年没有行,因为它的公司在那一年没有在乌干达投资)。所以 2003 年的 n1 应该是 2。关于如何改进它的任何想法?
      • 那么n1是年份在数据中出现的次数?
      • n1 是某年某 target_nation 的行数。 (在我的原始数据集中,乌干达不是唯一的目标国家——还有更多)。这有帮助吗?
      猜你喜欢
      • 2021-06-30
      • 1970-01-01
      • 1970-01-01
      • 2020-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多