lubridate 将小数转换为月份
lubridate convert decimals into months
我使用 lubridate
通过从出生日期 wdob
中减去结婚日期 wdow
来估计变量 age.first.union
作为时差。我得到以下数字向量
head(wm$age.first.union, 3)
[1] 15.43014 12.67123 17.34247
我想将小数转换成月(也可能转换成天,但这是次要细节),所以第一个值是 15 年零 5 个月。我所做的是创建一系列新变量,然后执行一些计算。为了获得月数,首先,我复制并截断了 age.first.union
变量。然后我估计两者之间的差异以仅获得小数部分,然后使用比例(例如 0.43 : 10 = x : 12
)来获得月份。
我查看了 lubridate
文档,但找不到太多相关信息。我尝试了以下
years(floor(dseconds(15.43014)))
但我只有年份
[1] "15y 0m 0d 0H 0M 0S"
一个想法是以秒为单位获取持续时间
seconds(floor(dyears(15.43014)))
[1] "486604895S"
但接下来的挑战是月份的长度不同。即使是年=365天,月=30天的近似值也会更完美,但除了冗长的计算,我不知道如何去做。
最后一个想法是使用本文开头所述的计算方法计算年和月 post,然后使用类似于 make_date
的方法将这两个变量合并到最后一个变量中(但看起来 make_duration
似乎还不存在)。
整个过程看起来很繁琐,谁有不同的看法?
非常感谢
马诺洛
虽然 lubridate
提供了一个函数 decimal_date
将小数 date 转换为 D-M-Y date,您似乎正在处理 durations。所以这行不通。
但是,您可以很容易地定义一个自定义函数来提取整数年、月和小数日(基于常规年份每月平均 30.42
天):
age <- c(15.43014 12.67123 17.34247)
f <- function(x) {
year <- floor(x);
month <- floor((x - year) * 12);
day <- ((x - year) * 12 - month) * 30.42;
return(sprintf("%i years, %i months, %3.2f days", year, month, day))
}
lapply(age, f);
#[[1]]
#[1] "15 years, 5 months, 4.92 days"
#
#[[2]]
#[1] "12 years, 8 months, 1.67 days"
#
#[[3]]
#[1] "17 years, 4 months, 3.34 days"
更新
如果你想return整数年、月和小数日你可以定义f
为
f <- function(x) {
year <- floor(x);
month <- floor((x - year) * 12);
day <- ((x - year) * 12 - month) * 30.42;
return(list(year = year, month = month, day = day))
}
这给你例如
sapply(age, f);
# [,1] [,2] [,3]
#year 15 12 17
#month 5 8 4
#day 4.918306 1.665799 3.335249
我们可以定义自己的ym
S3 class来表示year/month个对象。这里我们定义了几个 ym
方法以及年和月的提取函数。 as.data.frame.ym
方法是部分实现。我们将一个月定义为一年的 1/12。
as.ym <- function(x, ...) structure(x, class = "ym")
as.data.frame.ym <- function(x, ...)
structure(list(x), row.names = seq_along(x), class = "data.frame")
years.ym <- as.integer
months.ym <- function(x) 12 * as.numeric(x) %% 1
format.ym <- function(x, ...) paste0(years.ym(x), "Y ", round(months.ym(x)), "M")
print.ym <- function(x, ...) print(format(x), ...)
# test
x <- c(15.43014, 12.67123, 17.34247) # test input
xx <- as.ym(x)
xx
## [1] "15Y 5M" "12Y 8M" "17Y 4M"
DF <- data.frame(x, xx)
DF
x xx
1 15.43014 15Y 5M
2 12.67123 12Y 8M
3 17.34247 17Y 4M
years.ym(xx)
## [1] 15 12 17
months.ym(xx)
## [1] 5.16168 8.05476 4.10964
class(xx)
## [1] "ym"
天
为了将天数也包括在内,我们假设一年有 365.25 天,并且我们再次使用一年中的 12 个月。我们为此创建了一个 ymd
S3 class。
as.ymd <- function(x, ...) structure(x, class = "ymd")
as.data.frame.ymd <- function(x, ...)
structure(list(x), row.names = seq_along(x), class = "data.frame")
years.ymd <- as.integer
months.ymd <- function(x) as.integer(12 * as.numeric(x) %% 1)
days.ymd <- function(x) (365.25 * as.numeric(x)) %% (365.25 / 12)
format.ymd <- function(x, ...)
paste0(years.ymd(x), "Y ", as.integer(months.ymd(x)), "M ", round(days.ymd(x), 1), "D")
print.ymd <- function(x, ...) print(format(x), ...)
xx <- as.ymd(x)
xx
## [1] "15Y 5M 4.9D" "12Y 8M 1.7D" "17Y 4M 3.3D"
DF <- data.frame(x, xx)
DF
x xx
1 15.43014 15Y 5M 4.9D
2 12.67123 12Y 8M 1.7D
3 17.34247 17Y 4M 3.3D
years.ymd(xx)
## [1] 15 12 17
months.ymd(xx)
## [1] 5 8 4
days.ymd(xx)
## [1] 4.921135 1.666758 3.337167
class(xx)
## [1] "ymd"
我使用 lubridate
通过从出生日期 wdob
中减去结婚日期 wdow
来估计变量 age.first.union
作为时差。我得到以下数字向量
head(wm$age.first.union, 3)
[1] 15.43014 12.67123 17.34247
我想将小数转换成月(也可能转换成天,但这是次要细节),所以第一个值是 15 年零 5 个月。我所做的是创建一系列新变量,然后执行一些计算。为了获得月数,首先,我复制并截断了 age.first.union
变量。然后我估计两者之间的差异以仅获得小数部分,然后使用比例(例如 0.43 : 10 = x : 12
)来获得月份。
我查看了 lubridate
文档,但找不到太多相关信息。我尝试了以下
years(floor(dseconds(15.43014)))
但我只有年份
[1] "15y 0m 0d 0H 0M 0S"
一个想法是以秒为单位获取持续时间
seconds(floor(dyears(15.43014)))
[1] "486604895S"
但接下来的挑战是月份的长度不同。即使是年=365天,月=30天的近似值也会更完美,但除了冗长的计算,我不知道如何去做。
最后一个想法是使用本文开头所述的计算方法计算年和月 post,然后使用类似于 make_date
的方法将这两个变量合并到最后一个变量中(但看起来 make_duration
似乎还不存在)。
整个过程看起来很繁琐,谁有不同的看法?
非常感谢
马诺洛
虽然 lubridate
提供了一个函数 decimal_date
将小数 date 转换为 D-M-Y date,您似乎正在处理 durations。所以这行不通。
但是,您可以很容易地定义一个自定义函数来提取整数年、月和小数日(基于常规年份每月平均 30.42
天):
age <- c(15.43014 12.67123 17.34247)
f <- function(x) {
year <- floor(x);
month <- floor((x - year) * 12);
day <- ((x - year) * 12 - month) * 30.42;
return(sprintf("%i years, %i months, %3.2f days", year, month, day))
}
lapply(age, f);
#[[1]]
#[1] "15 years, 5 months, 4.92 days"
#
#[[2]]
#[1] "12 years, 8 months, 1.67 days"
#
#[[3]]
#[1] "17 years, 4 months, 3.34 days"
更新
如果你想return整数年、月和小数日你可以定义f
为
f <- function(x) {
year <- floor(x);
month <- floor((x - year) * 12);
day <- ((x - year) * 12 - month) * 30.42;
return(list(year = year, month = month, day = day))
}
这给你例如
sapply(age, f);
# [,1] [,2] [,3]
#year 15 12 17
#month 5 8 4
#day 4.918306 1.665799 3.335249
我们可以定义自己的ym
S3 class来表示year/month个对象。这里我们定义了几个 ym
方法以及年和月的提取函数。 as.data.frame.ym
方法是部分实现。我们将一个月定义为一年的 1/12。
as.ym <- function(x, ...) structure(x, class = "ym")
as.data.frame.ym <- function(x, ...)
structure(list(x), row.names = seq_along(x), class = "data.frame")
years.ym <- as.integer
months.ym <- function(x) 12 * as.numeric(x) %% 1
format.ym <- function(x, ...) paste0(years.ym(x), "Y ", round(months.ym(x)), "M")
print.ym <- function(x, ...) print(format(x), ...)
# test
x <- c(15.43014, 12.67123, 17.34247) # test input
xx <- as.ym(x)
xx
## [1] "15Y 5M" "12Y 8M" "17Y 4M"
DF <- data.frame(x, xx)
DF
x xx
1 15.43014 15Y 5M
2 12.67123 12Y 8M
3 17.34247 17Y 4M
years.ym(xx)
## [1] 15 12 17
months.ym(xx)
## [1] 5.16168 8.05476 4.10964
class(xx)
## [1] "ym"
天
为了将天数也包括在内,我们假设一年有 365.25 天,并且我们再次使用一年中的 12 个月。我们为此创建了一个 ymd
S3 class。
as.ymd <- function(x, ...) structure(x, class = "ymd")
as.data.frame.ymd <- function(x, ...)
structure(list(x), row.names = seq_along(x), class = "data.frame")
years.ymd <- as.integer
months.ymd <- function(x) as.integer(12 * as.numeric(x) %% 1)
days.ymd <- function(x) (365.25 * as.numeric(x)) %% (365.25 / 12)
format.ymd <- function(x, ...)
paste0(years.ymd(x), "Y ", as.integer(months.ymd(x)), "M ", round(days.ymd(x), 1), "D")
print.ymd <- function(x, ...) print(format(x), ...)
xx <- as.ymd(x)
xx
## [1] "15Y 5M 4.9D" "12Y 8M 1.7D" "17Y 4M 3.3D"
DF <- data.frame(x, xx)
DF
x xx
1 15.43014 15Y 5M 4.9D
2 12.67123 12Y 8M 1.7D
3 17.34247 17Y 4M 3.3D
years.ymd(xx)
## [1] 15 12 17
months.ymd(xx)
## [1] 5 8 4
days.ymd(xx)
## [1] 4.921135 1.666758 3.337167
class(xx)
## [1] "ymd"