簡體   English   中英

將面板數據中特定國家/地區的上一年值替換為 NA

[英]Replacing NAs with prior year value for specific country in panel data

我已經合並了兩個數據框,分別稱為 A 和 B。其中一個具有每年重要變量的值以及一些缺失的數據,我將分別處理這些數據。 第二個只有特定年份(選舉年)的值。 這是跨國家面板數據,具有國家年觀察單位,因此在任何操作中區分國家和年份非常重要。 合並后,非選舉年的數據如預期的那樣具有來自第二個 dataframe 的數據的 NA 值。 這些 NA 需要填寫該特定國家上一次選舉的數據,直到該國家的下一次選舉。 我不想為來自 dataframe A 的數據填寫任何 NA。

(對於可能有理論問題的人來說,B的數據是關於執政黨的,所以理論上這樣填寫數據是合理的。)

如果我按國家/地區對數據進行子集化,我可以使用 tidy::fill function 輕松完成此操作,方法是僅選擇包含來自 B 的數據的列。對於所有國家/地區的完整 dataframe,我不能這樣做,因為在某些情況下它會用 dataframe 中前一個國家的值填寫一個國家的開始年份。

這是數據排列的一個最小示例(請記住,實際數據中有 190 個國家和 9282 個觀測值):

country <- c("Austria","Austria","Austria","Austria","Austria",
         "Belgium","Belgium","Belgium","Belgium","Belgium")
year <- c("1999","2000","2001","2002","2003",
      "1999","2000","2001","2002","2003")
a1 <- c(5,4,NA,4,3,6,2,9,NA,7)
a2 <- c(45,53,57,51,33,37,12,48,55,41)
b1 <- c(NA,"A",NA,NA,NA,NA,NA,"B",NA,"C")
b2 <- c(NA,7,NA,NA,NA,NA,NA,5,NA,7)
df <- data.frame(country,year,a1,a2,b1,b2)
國家 a1 a2 b1 b2
奧地利 1999 5 45 不適用 不適用
奧地利 2000 4 53 一個 7
奧地利 2001年 不適用 57 不適用 不適用
奧地利 2002年 4 51 不適用 不適用
奧地利 2003年 3 33 不適用 不適用
比利時 1999 6 37 不適用 不適用
比利時 2000 2 12 不適用 不適用
比利時 2001年 9 48 5
比利時 2002年 不適用 55 不適用 不適用
比利時 2003年 7 41 C 7

這是我想要制作的:

國家 a1 a2 b1 b2
奧地利 1999 5 45 不適用 不適用
奧地利 2000 4 53 一個 7
奧地利 2001年 不適用 57 一個 7
奧地利 2002年 4 51 一個 7
奧地利 2003年 3 33 一個 7
比利時 1999 6 37 不適用 不適用
比利時 2000 2 12 不適用 不適用
比利時 2001年 9 48 5
比利時 2002年 不適用 55 5
比利時 2003年 7 41 C 7

在示例中,簡單地使用 tidy::fill 將導致比利時 1999 年和 2000 年的值不正確,因為它將填充來自奧地利的值。

正如Peace Wang 在評論中建議的那樣,您只需要group_by(country) 您可以利用tidy-select專門fill df B 中的列。

library(tidyverse)

country <- c("Austria","Austria","Austria","Austria","Austria",
             "Belgium","Belgium","Belgium","Belgium","Belgium")
year <- c("1999","2000","2001","2002","2003",
          "1999","2000","2001","2002","2003")
a1 <- c(5,4,NA,4,3,6,2,9,NA,7)
a2 <- c(45,53,57,51,33,37,12,48,55,41)
b1 <- c(NA,"A",NA,NA,NA,NA,NA,"B",NA,"C")
b2 <- c(NA,7,NA,NA,NA,NA,NA,5,NA,7)
df <- data.frame(country,year,a1,a2,b1,b2)

df %>% 
  group_by(country) %>% 
  arrange(year) %>% 
  fill(starts_with("b"), .direction = "down") %>% 
  arrange(country)
#> # A tibble: 10 x 6
#> # Groups:   country [2]
#>    country year     a1    a2 b1       b2
#>    <chr>   <chr> <dbl> <dbl> <chr> <dbl>
#>  1 Austria 1999      5    45 <NA>     NA
#>  2 Austria 2000      4    53 A         7
#>  3 Austria 2001     NA    57 A         7
#>  4 Austria 2002      4    51 A         7
#>  5 Austria 2003      3    33 A         7
#>  6 Belgium 1999      6    37 <NA>     NA
#>  7 Belgium 2000      2    12 <NA>     NA
#>  8 Belgium 2001      9    48 B         5
#>  9 Belgium 2002     NA    55 B         5
#> 10 Belgium 2003      7    41 C         7

代表 package (v0.3.0) 於 2021 年 12 月 26 日創建

我認為組country中的locf (最后一次觀察結轉)nafill 方法是您想要的。

library(data.table)
df = setDT(df)

cols = c("b1","b2")
df[,(cols):= lapply(.SD, zoo::na.locf, na.rm = FALSE),
    .SDcols = cols, 
    by = .(country)]

# data.table::nafill now can only process numeric columns, e.g. 
# df[, b2 := nafill(b2, type = c("locf"), by = .(country)]

你可以打開黑匣子然后做

toIm <- c("b1", "b2")

do.call(rbind, c(by(dat, dat$country, \(z) {
  z[toIm] <- lapply(z[toIm], \(y) {
    unlist(by(y, cumsum(!is.na(y)), \(x) 
              by(x, cumsum(!is.na(x)), \(w) rep(w[1], length(w)))))
  })
  z
}), make.row.names=F))
#    country year a1 a2   b1 b2
# 1  Austria 1999  5 45 <NA> NA
# 2  Austria 2000  4 53    A  7
# 3  Austria 2001 NA 57    A  7
# 4  Austria 2002  4 51    A  7
# 5  Austria 2003  3 33    A  7
# 6  Belgium 1999  6 37 <NA> NA
# 7  Belgium 2000  2 12 <NA> NA
# 8  Belgium 2001  9 48    B  5
# 9  Belgium 2002 NA 55    B  5
# 10 Belgium 2003  7 41    C  7

注: R version 4.1.2 (2021-11-01)


數據:

dat <- structure(list(country = c("Austria", "Austria", "Austria", "Austria", 
"Austria", "Belgium", "Belgium", "Belgium", "Belgium", "Belgium"
), year = c(1999L, 2000L, 2001L, 2002L, 2003L, 1999L, 2000L, 
2001L, 2002L, 2003L), a1 = c(5L, 4L, NA, 4L, 3L, 6L, 2L, 9L, 
NA, 7L), a2 = c(45L, 53L, 57L, 51L, 33L, 37L, 12L, 48L, 55L, 
41L), b1 = c(NA, "A", NA, NA, NA, NA, NA, "B", NA, "C"), b2 = c(NA, 
7L, NA, NA, NA, NA, NA, 5L, NA, 7L)), class = "data.frame", row.names = c(NA, 
-10L))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM