简体   繁体   English

如何在 r 中包含缺失的数据点

[英]How to include missing data points in r

This problem is a spin-off from my last post ( How to calculate moving average for two years in r ).这个问题是我上一篇文章( 如何计算 r 中两年的移动平均值)的衍生问题。

I have a big data frame (900k rows) about mergers and acquisitions (M&As).我有一个关于并购 (M&A) 的大数据框(90 万行)。

The df has four columns: date (when the M&A was completed), target_nation (a company of which country was merged/acquired), acquiror_nation (corporation of which country was the acquiror), and big_corp_TF (whether the acquiror was a big corporation or not, where TRUE means that corporation is big). df 有四列: date (并购完成时间)、 target_nation (被兼并/收购的国家/地区的公司)、 acquiror_nation (收购方是哪个国家/地区的公司)和big_corp_TF (收购方是大公司还是不是,TRUE 表示公司很大)。 Here is a sample of my data:这是我的数据示例:

> 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

NB: There are no rows for France in 2003;注意: 2003 年法国没有行; and there is no year 2005.并且没有 2005 年。

From these data, I want to create a new variable that denotes the share of M&As done by big corporations of specific acquiror nations, counting the average for 2 years.根据这些数据,我想创建一个新变量,表示特定收购国的大公司进行的并购份额,计算 2 年的平均值。 (For my actual exercise, I will count the averages for 5 years, but let's keep things simpler here). (对于我的实际练习,我将计算 5 年的平均值,但让我们在这里保持简单)。 So there would be a new variable for France's big corporations, and a new variable for Germany's big corporations.所以法国的大公司会有一个新的变量,德国的大公司会有一个新的变量。

I was suggested to use the following code:有人建议我使用以下代码:

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))

Which outputs this 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  2004 Uganda        France              3     1   0.5
5  2006 Uganda        France              2     2   0.6

NB: there is no result for France for 2003 and 2005;注意: 2003 年和 2005 年法国没有结果; I would like there to be results for 2003 and 2005 (because we are calculating 2-year averages and thus we should be able to have results for 2003 and 2005).我希望有 2003 年和 2005 年的结果(因为我们正在计算 2 年的平均值,因此我们应该能够获得 2003 年和 2005 年的结果)。 Also, the share for 2006 is incorrect in reality, because it should be 1 (it should take the values of 2005 (which are 0s) rather than the values of 2004 for the calculation of average).另外,2006 年的份额实际上是不正确的,因为它应该是 1(它应该取 2005 年的值(即 0)而不是 2004 年的值来计算平均值)。

I would like to be able to receive the following tibble:我希望能够收到以下 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

NB: notice that the result for 2006 is also different (because we now take 2005 instead of 2004 for a two-year average).注意:请注意,2006 年的结果也有所不同(因为我们现在将 2005 年而不是 2004 年作为两年平均值)。

I understand that this is a problem with the original data: it simply lacks certain data points.我知道这是原始数据的问题:它只是缺少某些数据点。 However, including them to the original data set seems to be highly inconvenient;但是,将它们包含在原始数据集中似乎非常不方便; it is probably better to include them mid-way, eg after counting the n1 and n2.中途包含它们可能会更好,例如在计算 n1 和 n2 之后。 But what is the most convenient way to do this?但是最方便的方法是什么?

Any suggestions are much appreciated.任何建议都非常感谢。

use tidyr::complete along with its arguments nesting and fill .使用tidyr::complete及其 arguments nestingfill Full code that may be used.可以使用的完整代码。

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
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    

Explanation解释

First, create df2 based on your df but without calculating share .首先,根据您的df创建df2但不计算share Create a sequence of dates from the minimum to the maximum:创建从最小值到最大值的日期序列:

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

Leave just the ones that are missing in df2 :只留下df2中缺少的那些:

dates = setdiff(dates, df2$date)

Create a row for each missing date and set n1 and n2 to 0:为每个缺失的日期创建一行并将n1n2设置为 0:

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

Combine the rows and sort by date:合并行并按日期排序:

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

Finally, calculate share :最后,计算share

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

I apologise that this doesn't adhere to the tidyverse syntax我很抱歉这不符合 tidyverse 语法

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM