我可以使用sapply执行以下操作,但我想如果dplyr也可以这样做,或者如果它是dplyr范围之外的问题。
我有三列,一列有日期(日期),一列有日期间隔(间隔),第三列有数值(值)。
我想要做的是每一行:
1)获取值Date
2)查看日期存在的时间间隔(%间隔内的日期%),并生成相应的布尔矢量
3)使用此布尔向量对整个原始数据帧进行子集化
4)取这个数据帧的值的平均值
5)将值存储在名为mean_for_Date
的新列中对于以下输入,列mean_for_Date的值将为3和1:
library(lubridate)
library(dplyr)
df <- data.frame( Date = as.Date(c("1998-01-02", "1998-01-06")), Values = c(1, 3))
df$Intervals <- c(interval(df[2, "Date"] - days(2), df[2, "Date"] + days(2)), interval(df[1, "Date"] - days(2), df[1, "Date"] + days(2)))
在sapply中,我这样做了:
df$mean_for_Date <- sapply(df$Date, function (x) mean(df$Values[x %within% df$Intervals], na.rm = T))
提前感谢所有可能的建议
答案 0 :(得分:2)
可以使用dummy
列在数据框cartesian join
的每一行之间应用df
以使其与itsefl自我加入,从而实现一种解决方案。
在准备加入时,我已经删除了一些不需要的列。笛卡尔联接提供Date
和Intervals
的所有可能组合。我将Values
与Interval
保持一致,以便在Date
匹配时,可以采用相应的Values
。
IsFound
决定Date
为within
间隔的行。我们只需filter
IsFound
行Values
为真,因为mean
的那些行将在该日期派生Date
。
如果在多个Interval
中找到group_by
,该解决方案将有效。 mean
最终有助于找到 library(dplyr)
df %>% select(-Values, - Intervals) %>% mutate(dummy = 1) %>%
inner_join(select(df, -Date) %>% mutate(dummy = 1), by="dummy") %>%
mutate(IsFound = Date %within% Intervals) %>%
filter(IsFound) %>%
select(-dummy, - IsFound) %>%
group_by(Date) %>%
summarise(Mean = mean(Values))
# A tibble: 2 x 2
# Date Mean
# <date> <dbl>
#1 1998-01-02 3.00
#2 1998-01-06 1.00
。
Static methods in interface require -target:jvm-1.8
答案 1 :(得分:2)
dplyr::mutate
中的{p> purrr::map_dbl
和tidyverse
可以执行相同的操作
library(lubridate) # date
library(magrittr) # %>% and %<>%
library(tidyverse) # mutate and map_dbl
df <- data.frame( Date = as.Date(c("1998-01-02", "1998-01-06")), Values = c(1, 3))
df$Intervals <- c(interval(df[2, "Date"] - days(2), df[2, "Date"] + days(2)),
interval(df[1, "Date"] - days(2), df[1, "Date"] + days(2)))
df %<>%
mutate(mean_for_Date = map_dbl(Date, ~ mean(Values[. %within% Intervals], na.rm = TRUE)))
df
#> Date Values Intervals mean_for_Date
#> 1 1998-01-02 1 1998-01-04 UTC--1998-01-08 UTC 3
#> 2 1998-01-06 3 1997-12-31 UTC--1998-01-04 UTC 1
str(df)
#> 'data.frame': 2 obs. of 4 variables:
#> $ Date : Date, format: "1998-01-02" "1998-01-06"
#> $ Values : num 1 3
#> $ Intervals :Formal class 'Interval' [package "lubridate"] with 3 slots
#> .. ..@ .Data: num 345600 345600
#> .. ..@ start: POSIXct, format: "1998-01-04" ...
#> .. ..@ tzone: chr "UTC"
#> $ mean_for_Date: num 3 1
由reprex package(v0.2.0)创建于2018-03-10。
答案 2 :(得分:0)
也许我太简单地看到问题了?如果日期落在区间内,这会得到平均值(作为日期的函数)吗?
df <- df %>%
left_join(df %>%
filter(Date %within% Intervals & !is.na(Values)) %>%
group_by(Date) %>%
summarise(mean_for_Date = mean(Values)) %>%
select(Date,mean_for_Date)), by="Date")