如何像 R 中的 SQL Windows 函数一样计算日差
How to calculate a day difference like a SQL Windows function in R
输入:
目标:
使用以下规则创建一个名为 'dayDifference' 的新列:对于每对 'item-city' 计算相关对的日差。
期望输出:
- 第 1 行和第 2 行 [Pair Piza-Berlin] 对应于 3,因为 2 月 2 日和 2 月 4 日之间有 3 天
- 第 3 行 [Pair Pizza-Hambourg] 对应 0,因为没有日差
- 第 4 行和第 5 行 [Pair Pasta-Hambourg] 对应 21 因为从 10 到 20 有 21 天
- 第 6 行 [Pair Pasta-Berlin] 对应 0,因为没有日差
信息:当然可以有超过 2 行的对 [例如我可以有对 'pizza-berlin' 100 行:如果是这样,总是取最大(日期)并减去最小(日期) 披萨-柏林对。
约束条件:
需要在 R 中完成 [例如没有与数据库的外部连接]
源代码:
df <- structure(list(id = c(4848L, 4887L, 4899L, 4811L, 4834L, 4892L
), item = structure(c(2L, 2L, 2L, 1L, 1L, 1L), .Label = c("Pasta",
"Pizza"), class = "factor"), city = structure(c(1L, 1L, 2L, 2L,
2L, 1L), .Label = c("Berlin", "Hamburg"), class = "factor"),
date = structure(c(17199, 17201, -643892, 17449, 17459, 17515
), class = "Date")), .Names = c("id", "item", "city", "date"
), row.names = c(NA, -6L), class = "data.frame")
不漂亮,但是...
i<-unique(lapply(1:nrow(df),function(x) which(paste(df[,2],df[,3]) %in% paste(df[x,2],df[x,3]))))
for(j in 1:length(i)) df[i[[j]],"days"]<-abs(difftime(df[i[[j]],][1,"date"],df[i[[j]],][2,"date"]))
> df
id item city date days
1 4848 Pizza Berlin 2017-02-02 2
2 4887 Pizza Berlin 2017-02-04 2
3 4899 Pizza Hamburg 0207-02-01 NA
4 4811 Pasta Hamburg 2017-10-10 10
5 4834 Pasta Hamburg 2017-10-20 10
6 4892 Pasta Berlin 2017-12-15 NA
我会使用 data.table
:
library(data.table)
setDT(df)
df[, min_date := min(date), by = c("item", "city")]
df[, max_date := max(date), by = c("item", "city")]
df[, dayDifference := difftime(max_date, min_date, units = "days")]
df[, c("min_date", "max_date") := NULL]
它会给你想要的输出:
id item city date dayDifference
1: 4848 Pizza Berlin 2017-02-02 2 days
2: 4887 Pizza Berlin 2017-02-04 2 days
3: 4899 Pizza Hamburg 0207-02-01 0 days
4: 4811 Pasta Hamburg 2017-10-10 10 days
5: 4834 Pasta Hamburg 2017-10-20 10 days
6: 4892 Pasta Berlin 2017-12-15 0 days
您也可以使用 df[, dayDifference := max_date - min_date]
代替 df[, dayDifference := difftime(max_date, min_date, units = "days")]
。
Reduce
是一个很棒的函数
library(dplyr)
df %>%
group_by(item, city) %>%
mutate(dayDifference=abs(Reduce(`-`, as.numeric(range(date)))))
# A tibble: 6 x 5
# Groups: item, city [4]
id item city date dayDifference
<int> <fctr> <fctr> <date> <dbl>
1 4848 Pizza Berlin 2017-02-02 2
2 4887 Pizza Berlin 2017-02-04 2
3 4899 Pizza Hamburg 0207-02-01 0
4 4811 Pasta Hamburg 2017-10-10 10
5 4834 Pasta Hamburg 2017-10-20 10
6 4892 Pasta Berlin 2017-12-15 0
输入:
目标:
使用以下规则创建一个名为 'dayDifference' 的新列:对于每对 'item-city' 计算相关对的日差。
期望输出:
- 第 1 行和第 2 行 [Pair Piza-Berlin] 对应于 3,因为 2 月 2 日和 2 月 4 日之间有 3 天
- 第 3 行 [Pair Pizza-Hambourg] 对应 0,因为没有日差
- 第 4 行和第 5 行 [Pair Pasta-Hambourg] 对应 21 因为从 10 到 20 有 21 天
- 第 6 行 [Pair Pasta-Berlin] 对应 0,因为没有日差
信息:当然可以有超过 2 行的对 [例如我可以有对 'pizza-berlin' 100 行:如果是这样,总是取最大(日期)并减去最小(日期) 披萨-柏林对。
约束条件:
需要在 R 中完成 [例如没有与数据库的外部连接]
源代码:
df <- structure(list(id = c(4848L, 4887L, 4899L, 4811L, 4834L, 4892L
), item = structure(c(2L, 2L, 2L, 1L, 1L, 1L), .Label = c("Pasta",
"Pizza"), class = "factor"), city = structure(c(1L, 1L, 2L, 2L,
2L, 1L), .Label = c("Berlin", "Hamburg"), class = "factor"),
date = structure(c(17199, 17201, -643892, 17449, 17459, 17515
), class = "Date")), .Names = c("id", "item", "city", "date"
), row.names = c(NA, -6L), class = "data.frame")
不漂亮,但是...
i<-unique(lapply(1:nrow(df),function(x) which(paste(df[,2],df[,3]) %in% paste(df[x,2],df[x,3]))))
for(j in 1:length(i)) df[i[[j]],"days"]<-abs(difftime(df[i[[j]],][1,"date"],df[i[[j]],][2,"date"]))
> df
id item city date days
1 4848 Pizza Berlin 2017-02-02 2
2 4887 Pizza Berlin 2017-02-04 2
3 4899 Pizza Hamburg 0207-02-01 NA
4 4811 Pasta Hamburg 2017-10-10 10
5 4834 Pasta Hamburg 2017-10-20 10
6 4892 Pasta Berlin 2017-12-15 NA
我会使用 data.table
:
library(data.table)
setDT(df)
df[, min_date := min(date), by = c("item", "city")]
df[, max_date := max(date), by = c("item", "city")]
df[, dayDifference := difftime(max_date, min_date, units = "days")]
df[, c("min_date", "max_date") := NULL]
它会给你想要的输出:
id item city date dayDifference
1: 4848 Pizza Berlin 2017-02-02 2 days
2: 4887 Pizza Berlin 2017-02-04 2 days
3: 4899 Pizza Hamburg 0207-02-01 0 days
4: 4811 Pasta Hamburg 2017-10-10 10 days
5: 4834 Pasta Hamburg 2017-10-20 10 days
6: 4892 Pasta Berlin 2017-12-15 0 days
您也可以使用 df[, dayDifference := max_date - min_date]
代替 df[, dayDifference := difftime(max_date, min_date, units = "days")]
。
Reduce
是一个很棒的函数
library(dplyr)
df %>%
group_by(item, city) %>%
mutate(dayDifference=abs(Reduce(`-`, as.numeric(range(date)))))
# A tibble: 6 x 5
# Groups: item, city [4]
id item city date dayDifference
<int> <fctr> <fctr> <date> <dbl>
1 4848 Pizza Berlin 2017-02-02 2
2 4887 Pizza Berlin 2017-02-04 2
3 4899 Pizza Hamburg 0207-02-01 0
4 4811 Pasta Hamburg 2017-10-10 10
5 4834 Pasta Hamburg 2017-10-20 10
6 4892 Pasta Berlin 2017-12-15 0