tidyr学习笔记一:用fill和complete处理缺失值NA

tidyr学习笔记一:用fill和complete处理缺失值NA

一、complete函数

complete函数用来把隐式的缺失值转换成正常显示的缺失值。

#A tibble: 7 x 3
  year   qtr return
  <dbl> <dbl>  <dbl>
1  2015     1   1.88`
2  2015     2   0.59`
3  2015     3   0.35`
4  2015     4  NA  
5  2016     2   0.92
6  2016     3   0.17
7  2016     4   2.66

在日常的数据透视中,会经常遇到经计算后,由于某些组别为0,出现若干隐式缺失值的情况。

例如上表中,2015年第四季度的return值为正常显示的显式缺失值,而2016年第一季度的return值则直接未在表中出现,为隐式缺失值。

函数用法:

complete(data, ..., fill = list())

complete包含三大参数,分别为

data,操作的数据框;

... 需要完善的变量名,显然,可以传入不止一个变量,达到一次补充多个变量缺失的目的,如果指定的变量为因子变量,默认将会把所有缺失的分类都补回数据中,如果只想补充数据中出现过的分类,那么需要将其去因子化后再进行操作;

fill = list(),如果不想用NA填充补充上隐式缺失值,可以通过fill传入一个列表,如果有多个变量,那每个变量可以分别指定一个值来代替NA。

帮助文档中的例子:

df <- tibble(
 group = c(1:2, 1),
 item_id = c(1:2, 2),
 item_name = c("a", "b", "b"),
 value1 = 1:3,
 value2 = 4:6
)

# A tibble: 3 x 5
 group item_id item_name value1 value2
 <dbl>   <dbl> <chr>      <int>  <int>
1     1       1 a              1      4
2     2       2 b              2      5
3     1       2 b              3      6

构造一个tibble,显然,这个tibble的group,item_id和item_name分组都是存在缺失的。

df %>% complete(group, nesting(item_id, item_name))

# A tibble: 4 x 5
 group item_id item_name value1 value2
 <dbl>   <dbl> <chr>      <int>  <int>
1     1       1 a              1      4
2     1       2 b              3      6
3     2       1 a             NA     NA
4     2       2 b              2      5

用complete处理后,缺失的分组都被补了回去,这里用 nesting(item_id, item_name) 是因为item_id和item_name其实是一一对应关系,1和a、2和b是成对的,如果不是成对关系,可以直接写成:

df %>% complete(group,item_id, item_name)

# A tibble: 8 x 5
 group item_id item_name value1 value2
 <dbl>   <dbl> <chr>      <int>  <int>
1     1       1 a              1      4
2     1       1 b             NA     NA
3     1       2 a             NA     NA
4     1       2 b              3      6
5     2       1 a             NA     NA
6     2       1 b             NA     NA
7     2       2 a             NA     NA
8     2       2 b              2      5

当然可以用fill来指定某个值来替代NA来填充补充上来的数据。

df %>% complete(group, nesting(item_id, item_name), fill = list(value1 = 0))

# A tibble: 4 x 5
 group item_id item_name value1 value2
 <dbl>   <dbl> <chr>      <dbl>  <int>
1     1       1 a              1      4
2     1       2 b              3      6
3     2       1 a              0     NA
4     2       2 b              2      5

变量为因子变量时:

df <- tibble(sex = c(rep('男',4),rep('女',2)),age=c('0~','15~','55~','85~','5~','10~'),pop = c(4,2,1,3,10,4))

# A tibble: 6 x 3
sex   age     pop
<chr> <chr> <dbl>
1 男   0~       4
2 男   15~       2
3 男   55~       1
4 男   85~       3
5 女   5~       10
6 女   10~       4

构造一个透视过的数据,我们需要的是年龄分成19组的数据,但是其他分组由于数据为0都被隐去了,把age转换成因子变量再用complete操作补回就变得非常简单。

labels19 <- c('0~','1~','5~','10~','15~','20~','25~','30~','35~',
'40~','45~','50~','55~','60~','65~','70~','75~','80~','85~')

df %>% mutate(age = factor(age,levels = labels19)) %>%
      complete(age,sex,fill = list(pop = 0))
     
 # A tibble: 38 x 3
  age   sex     pop
  <fct> <chr> <dbl>
1 0~   男        4
2 0~   女        0
3 1~   男        0
4 1~   女        0
5 5~   男        0
6 5~   女       10
7 10~   男        0
8 10~   女        4
9 15~   男        2
10 15~   女        0
# ... with 28 more rows

 

二、fill函数

fill函数可以将选中变量列的缺失值填充完整,可以选择从上往下填充或者从下往上填充,这个函数非常契合因变量数据因重复而被省略仅有变化时才输入的场景。

参数

data 被操作的数据框;

... 变量列,与complete一样,可以传入多个变量列进行操作;

direction 默认值为down,即从上向下填充,其他的值还有up,downup(先向下再向上),updown(先向上再向下。

帮助文档中的例子:

sales <- tibble::tribble(
 ~quarter, ~year, ~sales,
 "Q1",    2000,    66013,
 "Q2",      NA,    69182,
 "Q3",      NA,    53175,
 "Q4",      NA,    21001,
 "Q1",    2001,    46036,
 "Q2",      NA,    58842,
 "Q3",      NA,    44568,
 "Q4",      NA,    50197,
 "Q1",    2002,    39113,
 "Q2",      NA,    41668,
 "Q3",      NA,    30144,
 "Q4",      NA,    52897,
 "Q1",    2004,    32129,
 "Q2",      NA,    67686,
 "Q3",      NA,    31768,
 "Q4",      NA,    49094
)

# A tibble: 16 x 3
  quarter  year sales
  <chr>   <dbl> <dbl>
1 Q1       2000 66013
2 Q2         NA 69182
3 Q3         NA 53175
4 Q4         NA 21001
5 Q1       2001 46036
6 Q2         NA 58842
7 Q3         NA 44568
8 Q4         NA 50197
9 Q1       2002 39113
10 Q2         NA 41668
11 Q3         NA 30144
12 Q4         NA 52897
13 Q1       2004 32129
14 Q2         NA 67686
15 Q3         NA 31768
16 Q4         NA 49094

用fill操作后,默认向下填充

sales %>% fill(year)

# A tibble: 16 x 3
  quarter  year sales
  <chr>   <dbl> <dbl>
1 Q1       2000 66013
2 Q2       2000 69182
3 Q3       2000 53175
4 Q4       2000 21001
5 Q1       2001 46036
6 Q2       2001 58842
7 Q3       2001 44568
8 Q4       2001 50197
9 Q1       2002 39113
10 Q2       2002 41668
11 Q3       2002 30144
12 Q4       2002 52897
13 Q1       2004 32129
14 Q2       2004 67686
15 Q3       2004 31768
16 Q4       2004 49094
squirrels <- tibble::tribble(
 ~group,    ~name,     ~role,     ~n_squirrels,
 1,      "Sam",    "Observer",   NA,
 1,     "Mara", "Scorekeeper",    8,
 1,    "Jesse",    "Observer",   NA,
 1,      "Tom",    "Observer",   NA,
 2,     "Mike",    "Observer",   NA,
 2,  "Rachael",    "Observer",   NA,
 2,  "Sydekea", "Scorekeeper",   14,
 2, "Gabriela",    "Observer",   NA,
 3,  "Derrick",    "Observer",   NA,
 3,     "Kara", "Scorekeeper",    9,
 3,    "Emily",    "Observer",   NA,
 3, "Danielle",    "Observer",   NA
)

# A tibble: 12 x 4
  group name     role        n_squirrels
  <dbl> <chr>    <chr>             <dbl>
1     1 Sam      Observer             NA
2     1 Mara     Scorekeeper           8
3     1 Jesse    Observer             NA
4     1 Tom      Observer             NA
5     2 Mike     Observer             NA
6     2 Rachael  Observer             NA
7     2 Sydekea  Scorekeeper          14
8     2 Gabriela Observer             NA
9     3 Derrick  Observer             NA
10     3 Kara     Scorekeeper           9
11     3 Emily    Observer             NA
12     3 Danielle Observer             NA

squirrels %>%
 dplyr::group_by(group) %>%
 fill(n_squirrels, .direction = "downup") %>%
 dplyr::ungroup()

# A tibble: 12 x 4
  group name     role        n_squirrels
  <dbl> <chr>    <chr>             <dbl>
1     1 Sam      Observer              8
2     1 Mara     Scorekeeper           8
3     1 Jesse    Observer              8
4     1 Tom      Observer              8
5     2 Mike     Observer             14
6     2 Rachael  Observer             14
7     2 Sydekea  Scorekeeper          14
8     2 Gabriela Observer             14
9     3 Derrick  Observer              9
10     3 Kara     Scorekeeper           9
11     3 Emily    Observer              9
12     3 Danielle Observer              9

这个数据集的有效数据分布在缺失值中,且1、2、3组每组各有一个有效数据,因此通过group_by分组分组后,再用fill进行操作,方式为downup,此案例中updown也能达到相同的效果,记得操作完之后要进行ungroup()操作,否则再对数据进行其他操作时,可能会出现意想不到的错误。

posted @ 2022-04-23 21:56  池哈哈  阅读(1876)  评论(0)    收藏  举报