技巧 | 数据有缺失值情况下的一个处理方法

本篇分享一个处理技巧,也来自一位读者的咨询。示例数据如下所示(可在后台回复关键词示例数据获得)。

66a644d2e508dce4996a868324543875.png

A2000-A2020五列为日期格式,其中包含缺失值;Year为某事件发生的年份。要求生成两列数据:

  • 第一列为事件发生的具体日期,也就是变量Year中的年份所对应前五列中的日期。如第一行对应的就是A2015列中的日期,第二行对应的是A2020列中的日期;

  • 第二列为发生日期之前的第一个非缺失日期。如第一行为A2010列的日期,第二行本应该是A2015列的日期,但是该列为缺失值,因此递补为A2010列的日期。

导入数据

test <- read.csv("104.缺失值test.csv",
                 stringsAsFactors = F,
                 na.strings = "",
                 fileEncoding = "UTF-8-BOM")

此步实际的参数功能如下:

  • stringsAsFactors = F:默认状态下,read.csv()函数会把字符变量当作是因子变量,该语句可避免这一情况;

  • na.strings = "":将空字符串(即"")当作是缺失值;

  • fileEncoding = "UTF-8-BOM":防止列名乱码。

  • 读者可分别去掉相应语句比较数据导入的效果。

08c9bcdc30a92043955bf59f07b0cbe8.png

转换日期格式

将前五列转为日期格式:

library(magrittr)
library(tidyverse)
test %<>%
  mutate(across(starts_with("A"),as.Date))
989b4d4182f2818d139293faa19d7fae.png

这里使用的across()函数是一个批量处理函数,可以参见以下两篇推文:

生成第一个变量

生成第一个变量的思路比较简单,只需要根据Year中的年份提取相应列中的数据即可。直接的方法是使用多层的if语句,不过dplyr工具包提供了一个更快捷的函数case_when()

test %<>%
  mutate(t1 = case_when(
    Year == "2020"~A2020,
    Year == "2015"~A2015,
    Year == "2010"~A2010,
    Year == "2005"~A2005,
  ))
6571bc29cf6818f0ffc052967a502230.png

生成第二个变量

相比之下,生成第二个变量的思路就不那么简单了,即使想使用if语句其逻辑也不是那么清晰。

小编的解决思路如下:

首先是把Year对应年份及其之后的日期全部转为缺失值。

为了不污染原始数据,这里使用一个临时数据框test0:

test0 = test
test0$A2020 = NA
test0$A2015[test0$Year <= 2015] = NA
test0$A2010[test0$Year <= 2010] = NA
test0$A2005[test0$Year <= 2005] = NA
01426fac2f6cdb54742411d961457251.png

此时,test0中各行最大的一个日期即为所求的第二个变量。

小编不清楚日期怎么比较大小,因此先将它们转为数值变量,方法同上:

test0 %<>%
  mutate(across(starts_with("A"),as.numeric))
a161c9485fb0d35bc46299bb5e2bdc55.png

max()函数可以用于求最大值:

test0 %<>%
  mutate(t2 = max(A2015, A2010, A2005, A2000,
                  na.rm = T))
  • na.rm = T:设置缺失值不参与计算。

582df08edeb51e44b3bc1feae9e0c2be.png

可以发现,上面代码计算的变量所有行的数值都是一样的,因为它是针对所有的数值求最大值的,这与预期目标不符。为了能够按行求最大值,需要在其在其使用rowwise()函数:

test0 %<>%
  rowwise() %>%
  mutate(t2 = max(A2015, A2010, A2005, A2000,
                  na.rm = T))
bfc227e73b37c49527261973717fdeb7.png

再把数值变量转为日期变量:

test$t2 <- as.Date(test0$t2, origin = "1970-1-1")
  • R中默认1970年1月1日对应的数值为0。

881ab6ac833625acb29dedea7abb7932.png

需要示例数据请在后台回复关键词示例数据

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值