要点:
大家好。
我目前正在处理多个大型数据集(大约200套,每组大于5000行)的长期时间序列数据集,用于跨不同位置的多个变量。到目前为止,我已经将数据提取到每个站点和每个站的单独CSV文件中。
在大多数情况下,每个参数报告的数据是每个季节一个实例。
这里的季节在生态上被定义为DJF,MAM,JJA,SON,分别对应于冬季,春季,夏季和秋季。
但是,在某些季节性事件中,有些情况下会有多个读数。这里,参数值和日期必须平均;这是在对这些数据集进行进一步分析之前。
为了使事情进一步复杂化,一些数据用大于或小于(GTLT)符号标记。在这些情况下,值和日期不是的平均值,除非记录的值相同。
要点:
所以,对于数据驱动的例子......
这是数据集中的几行。
Data.Example<-structure(list(
Station.ID = c(13402, 13402, 13402, 13402, 13402, 13402),
End.Date = structure(c(2L, 3L, 4L, 2L, 3L, 1L), .Label = c("10/13/2016", "7/13/2016", "8/13/2016", "8/15/2016"), class = "factor"),
Parameter.Name = structure(c(2L, 2L, 2L, 1L, 1L, 1L), .Label = c("Alkalinity", "Enterococci"), class = "factor"),
GTLT = structure(c(2L, 2L, 2L, 1L, 1L, 1L), .Label = c("", "<"), class = "factor"),
Value = c(10, 10, 20, 30, 15, 10)),
.Names = c("Station.ID", "End.Date", "Parameter.Name","GTLT", "Value"), row.names = c(NA, -6L), class = "data.frame")
理想情况下,这是我想要的输出
Data.Example.New<-structure(list(
Station.ID.new = c(13402, 13402, 13402, 13402),
End.Date.new = structure(c(2L, 3L, 2L, 1L), .Label = c("10/13/2016", "7/28/2016", "8/15/2016"), class = "factor"),
Parameter.Name.new = structure(c(2L, 2L, 1L, 1L), .Label = c("Alkalinity", "Enterococci"), class = "factor"),
GTLT.new = structure(c(2L, 2L, 1L, 1L), .Label = c("", "<"), class = "factor"),
Value.new = c(10, 20, 22.5, 10)),
.Names = c("Station.ID.new", "End.Date.new", "Parameter.Name.new", "GTLT.new", "Value.new"), row.names = c(NA, -4L), class = "data.frame")
在这里,发生了以下事情:
如果由于某种原因你有相同参数的GTLT和非GTLT:
End.Date GTLT Value Parameter
7/13/2015 < 10 Alk
7/13/2016 < 10 Alk
8/13/2016 10 Alk
8/15/2016 20 Alk
然后最终结果将是
End.Date GTLT Value Parameter
7/13/2015 < 10 Alk
7/13/2016 < 10 Alk
8/14/2016 15 Alk
要点:
dplyr
正如人们所料,这就是我被困住的地方。
我知道可以在之前的Stack Q中用R定义季节:
New vector of seasons based on dates
我知道平均/聚合包,例如dplyr
(可能zoo
?)可以执行链接命令。
我的问题是将这个思维过程放入可以为每个数据集重复的代码中。
我不确定这是否是最好的方法(定义季节然后设置平均数据的条件),或者如果某种循环函数在这里通过参数排序后逐行遍历数据集将起作用.Name然后是End.Date。
我很快勾勒出我对某些循环函数必须包含的内容的想法:
注意,你不能只平均起始行[i]和[i + 1],因为[i + 2]等也可能需要平均。因此找到行[i + n]在最后一步之前打破循环,平均所有先前行[i + n-1],然后继续前进到下一个新行[i + n]。
此外,作为澄清,季节必须在该年度周期的季节内。所以7/13/2016 == 8/13/2016同一季节。 12/12/2015 == 01/01/2016同一季节。但是2016年4月13日! == 4/13/2015关于平均值。
简而言之,我需要帮助设计代码,以便按年度季节平均各个参数的时间序列值,并为多个大型数据集提供特定的例外情况。
我不确定设计代码的最佳方法,无论是大型循环函数还是代码和专用链接启用软件包的组合。
感谢您提前抽出时间。
干杯,
soccernamlak
答案 0 :(得分:0)
使用dplyr
和lubridate
我能够提出解决方案。我的输出与你的示例输出相匹配,除了我没有保留确切的日期,我认为这在最终结果中会产生误导。
Data.Example<-structure(list(
Station.ID = c(13402, 13402, 13402, 13402, 13402, 13402),
End.Date = structure(c(2L, 3L, 4L, 2L, 3L, 1L), .Label = c("10/13/2016", "7/13/2016", "8/13/2016", "8/15/2016"), class = "factor"),
Parameter.Name = structure(c(2L, 2L, 2L, 1L, 1L, 1L), .Label = c("Alkalinity", "Enterococci"), class = "factor"),
GTLT = structure(c(2L, 2L, 2L, 1L, 1L, 1L), .Label = c("", "<"), class = "factor"),
Value = c(10, 10, 20, 30, 15, 10)),
.Names = c("Station.ID", "End.Date", "Parameter.Name","GTLT", "Value"), row.names = c(NA, -6L), class = "data.frame")
# Create season key
seasons <- data.frame(month = 1:12, season = c(rep("DJF",2), rep("MAM", 3), rep("JJA", 3), rep("SON",3), "DJF"))
# Isolate Month and Year, create Season column
Data.Example$Month <- lubridate::month(as.Date((Data.Example$End.Date), "%m/%d/%Y"))
Data.Example$Year <- lubridate::year(as.Date((Data.Example$End.Date), "%m/%d/%Y"))
Data.Example$Season <- seasons$season[Data.Example$Month]
# Update 'year' where month = December so that it is grouped with Jan and Feb of following year
Data.Example$Year[Data.Example$Month == 12] <- Data.Example$Year[Data.Example$Month == 12]+1
# Find out which station/year/season/paramaters have at least one record with a GTLT
GTLT.Test<- Data.Example %>%
group_by(Station.ID, Year, Season, Parameter.Name) %>%
summarize(has_GTLT = max(nchar(as.character(GTLT))))
# First only calculate averages for groups without any GTLT
Data.Example.New1 <- Data.Example %>%
anti_join(GTLT.Test[GTLT_test$has_GTLT == 1,],
by = c("Station.ID", "Year", "Season", "Parameter.Name")) %>%
group_by(Station.ID, Year, Season, Parameter.Name, GTLT) %>%
summarize(Value.new = mean(Value))
# Now do the same for groups with GTLT, only combining when values and GTLT symbols match.
Data.Example.New2 <- Data.Example %>%
anti_join(GTLT.Test[GTLT_test$has_GTLT == 0,],
by = c("Station.ID", "Year", "Season", "Parameter.Name")) %>%
group_by(Station.ID, Year, Season, Parameter.Name, GTLT, Value) %>%
summarize(Value.new = mean(Value)) %>%
select(-Value)
# Combine both
Data.Example.New <- rbind(Data.Example.New1, Data.Example.New2)
编辑:我刚刚注意到您将另一个SO问题与日期转换为季节相关联。我只是按月而不是按日期转换,并且不使用实际季节。我这样做是因为在你的例子中,12月12日与1月1日比赛。12月12日在技术上下降,所以我假设你没有使用实际的季节,而是使用了四个三个月的分组。