问题描述
(我实际上想出了一个解决方案,但这并不能满足我对简单性和直观性的渴望,因此我在这里陈述我的问题和解决方案,同时等待一个漂亮而简洁的解决方案。)
我有一个数据,一列是Year
,另一列是Month
,而月份是字符串格式:
Country Month Year Type
<fct> <chr> <dbl> <fct>
1 Argentina June 1975 Currency
2 Argentina February 1981 Currency
3 Argentina July 1982 Currency
我正在尝试将 Month 和 Year 列合并为单个列 Date
,其格式为 date
。
第一次尝试
我的第一次尝试是在 mapply
的帮助下使用 lubridate
和我的一个将 month
从字符串转换为整数的小函数。
months = c("January","February","march","April",'May','June','July','August','September','October','November','December')
month_num = c(1:12)
names(month_num) = months
crisis$Date = mapply(function(y,m){
m = month_num[m]
d = make_date(y,m)
return(d)
},crisis$Year,crisis$Month)
然而这并不是我想要的:
Country Month Year Type Date
<fct> <chr> <dbl> <fct> <list>
1 Argentina June 1975 Currency <date [1]>
2 Argentina February 1981 Currency <date [1]>
3 Argentina July 1982 Currency <date [1]>
4 Argentina September 1986 Currency <date [1]>
,因为 Date
列是列表格式。
一些谷歌搜索
在 this post 的帮助下,以及将其取消列出并将其恢复为日期对象的一些操作,我设法得到了我想要的结果:
crisis$Date = as_date(unlist(mapply(function(y,crisis$Month,SIMPLIFY = FALSE)))
结果是
Country Month Year Type Date
<fct> <chr> <dbl> <fct> <date>
1 Argentina June 1975 Currency 1975-06-01
2 Argentina February 1981 Currency 1981-02-01
3 Argentina July 1982 Currency 1982-07-01
4 Argentina September 1986 Currency 1986-09-01
到目前为止,这还可以处理,但我相信有更好的解决方案。
解决方法
您可以将月份转换为数字,然后再转换为日期:
df %>%
mutate(
Month = base::match(Month,base::month.name),Date = as.Date(paste(Year,'-',Month,'-01',sep=''))
) %>%
select(-c(Month,Year))
# A tibble: 3 x 3
# Country Type Date
# <chr> <chr> <date>
# 1 Argentina Currency 1975-06-01
# 2 Argentina Currency 1981-02-01
# 3 Argentina Currency 1982-07-01
这有帮助吗?
我提供了以下数据框:
library(tibble)
df <- tibble(
Country = 'Argentina',Month = c('June','February','July'),Year = c(1975,1981,1982),Type = 'Currency'
)
,
df$Date <- lubridate::myd(paste(df$Month,df$Year,"1"))
,
所以在 @Gram 和 @det 的帮助下,我想出了我的解决方案。
我是 R 的新学习者,所以我没有意识到处理数据的一些 R 风格,因此试图在一行代码中完成所有事情。感谢 Gram 的回答中的一些提示,我以某种方式学会了通过添加辅助列来清除我的代码(类似于 excel)。
考虑到未来可能出现的情况可能不是简单地从 1:12 到几个月的通信,并且为了使事情更通用以供将来使用,我创建了一个新的 data.frame
来存储所有有关月份的信息:
month_ref = data.frame(num = 1:12,Month = c("January","February","March","April",'May','June','July','August','September','October','November','December'))
num Month
1 1 January
2 2 February
3 3 March
4 4 April
现在的想法是“组合”两个数据框,将 Month
列与数字匹配。这与 Excel 中的 VLOOKUP
函数完全一样,在 this post 的帮助下,我现在有一个包含一列数字的数据框
crisis = crisis %>%
inner_join(month_ref,by=c("Month"))
Country Month Year Type num
<fct> <chr> <dbl> <fct> <int>
1 Argentina June 1975 Currency 6
2 Argentina February 1981 Currency 2
3 Argentina July 1982 Currency 7
4 Argentina September 1986 Currency 9
然后,我可以使用一列整齐的月份数字处理我的数据框,这比在 mutate()
中处理自定义函数中的解析更容易和可读。
crisis = crisis %>%
inner_join(month_ref,by="Month") %>%
mutate(
Date = lubridate::ymd(paste(Year,num,"01",sep="-"))
) %>%
select(-c(num,Year))
Country Type Date
<fct> <fct> <date>
1 Argentina Currency 1975-06-01
2 Argentina Currency 1981-02-01
3 Argentina Currency 1982-07-01