本篇分享一个处理技巧,也来自一位读者的咨询。示例数据如下所示(可在后台回复关键词示例数据获得)。
![66a644d2e508dce4996a868324543875.png](https://i-blog.csdnimg.cn/blog_migrate/caf448bb76f260acc06e511595a98e49.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](https://i-blog.csdnimg.cn/blog_migrate/831e84b34412e5b5b6b0b4eed8e9e279.png)
转换日期格式
将前五列转为日期格式:
library(magrittr)
library(tidyverse)
test %<>%
mutate(across(starts_with("A"),as.Date))
![989b4d4182f2818d139293faa19d7fae.png](https://i-blog.csdnimg.cn/blog_migrate/4c5dd0c0b0595f35f97be00a8e788f4c.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](https://i-blog.csdnimg.cn/blog_migrate/68ed0ca5764dfb3dd41bd7240500d568.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](https://i-blog.csdnimg.cn/blog_migrate/c4d6353889c6da8bf7b0fcf9514608aa.png)
此时,test0
中各行最大的一个日期即为所求的第二个变量。
小编不清楚日期怎么比较大小,因此先将它们转为数值变量,方法同上:
test0 %<>%
mutate(across(starts_with("A"),as.numeric))
![a161c9485fb0d35bc46299bb5e2bdc55.png](https://i-blog.csdnimg.cn/blog_migrate/324372e9aeb5c3948b66e3178c8fb25e.png)
max()
函数可以用于求最大值:
test0 %<>%
mutate(t2 = max(A2015, A2010, A2005, A2000,
na.rm = T))
na.rm = T
:设置缺失值不参与计算。
![582df08edeb51e44b3bc1feae9e0c2be.png](https://i-blog.csdnimg.cn/blog_migrate/ec17f59d78ee9c096e0740b985314836.png)
可以发现,上面代码计算的变量所有行的数值都是一样的,因为它是针对所有的数值求最大值的,这与预期目标不符。为了能够按行求最大值,需要在其在其使用rowwise()
函数:
test0 %<>%
rowwise() %>%
mutate(t2 = max(A2015, A2010, A2005, A2000,
na.rm = T))
![bfc227e73b37c49527261973717fdeb7.png](https://i-blog.csdnimg.cn/blog_migrate/dad8c7ad356a4530e11d4c30bb625753.png)
再把数值变量转为日期变量:
test$t2 <- as.Date(test0$t2, origin = "1970-1-1")
R中默认1970年1月1日对应的数值为0。
![881ab6ac833625acb29dedea7abb7932.png](https://i-blog.csdnimg.cn/blog_migrate/e9be225785a56fdecf11665e09a40113.png)
需要示例数据请在后台回复关键词示例数据。