我想计算几年中每天的趋势。例如,从2000年到2010年5月1日的趋势。这是我的测试数据框:
library(lubridate)
date_list = seq(ymd('2000-01-15'),ymd('2010-09-18'),by='day')
testframe = data.frame(Date = date_list)
testframe$Day = substr(testframe$Date, start = 6, stop = 10)
testframe$V1 = rnorm(3900)
testframe$V2 = rnorm(3900)
testframe$V3 = seq(from = 10, to = 25, length.out = 3900)
testframe$V4 = seq(from = 5, to = 45, length.out = 3900)
V1至V4是值。在testframe $ Day中,我已经删除了日期,因此可以使用它来对行进行分组。我知道aggregate
很适合以此方式进行分组,但是我对如何将其与线性模型结合起来一无所知。
最后,我希望有一个数据框,该数据框具有一个包含每一天(当然没有年份)的列,以及一个包含从V1到V4的值的趋势/斜率的列。
有什么想法吗?
更新:
使其更加清晰。我想要的输出看起来像这样(趋势是随机的)
Day V1 Trend V2 Trend V3 Trend V4 Trend
01-01 +0.3 +0.4 +0.9 +0.5
01-02 +0.5 +0.3 +0.8 +0.4
01-03 -0.1 -0.2 +1.0 -0.3
01-04 +0.7 -0.7 +0.9 +0.9
......
......
12-30 -0.3 -0.4 +0.5 +0.8
12-31 -0.7 -0.3 +0.6 +0.9
p值,拦截和所有这些都很好。
我找到了这个示例,但是它仍然不在我想要的输出中:
#Add year for lm
testframe$Year = as.numeric(format(testframe$Date,'%Y'))
library(plyr)
# Break up d by state, then fit the specified model to each piece and
# return a list
models <- dlply(testframe, "Day", function(df)
lm(Year ~ V4, data = df))
# Apply coef to each model and return a data frame
ldply(models, coef)
# Print the summary of each model
l_ply(models, summary, .print = TRUE)
答案 0 :(得分:1)
这将为每个V列的每年的每一天提供单独的截距和斜率。 (yday
是0、1、2,...和ydayf
相同的年份,但作为一个因子,yr
是4位数字的年份。)>
m <- as.matrix(testframe[-(1:2)])
yday <- as.POSIXlt(testframe$Date)$yday
ydayf <- factor(yday)
yr <- as.numeric(format(testframe$Date, "%Y"))
fm2 <- lm(m ~ ydayf + ydayf:yr + 0)
coef(fm2)
dummy.coef(fm2) # expand coefficients
summary(fm2)
broom::tidy(fm2) # data frame
如果您想要单独的斜率,但仅需一个截距,则可以在每个V列中使用。
fm3 <- lm(m ~ ydayf:yr)
coef(fm3)
dummy.coef(fm3) # expands coefficients
summary(fm3)
broom::tidy(fm3) # data frame
如果您想要单独的截距,但每个V列只有一个斜率,那么:
fm4 <- lm(m ~ ydayf + yr + 0)
coef(fm4)
dummy.coef(fm4) # expands coefficients
summary(fm4)
broom::tidy(fm4) # data frame
带有S Plus的现代应用统计这本书是lm
公式的很好参考。
答案 1 :(得分:1)
从您的输出中,您似乎要为每个Day
建立一个V ~ Year
形式的线性模型。
这是一种V1, V2, V3, V4
的方法:
dplyr
如果您想将列名更新为类似library(lubridate)
library(dplyr)
set.seed(23) # for reproducibility
# data (using your code)
date_list = seq(ymd('2000-01-15'),ymd('2010-09-18'),by='day')
testframe = data.frame(Date = date_list)
testframe$Day = substr(testframe$Date, start = 6, stop = 10)
testframe$V1 = rnorm(3900)
testframe$V2 = rnorm(3900)
testframe$V3 = seq(from = 10, to = 25, length.out = 3900)
testframe$V4 = seq(from = 5, to = 45, length.out = 3900)
testframe %>%
mutate(Year = year(Date)) %>% # extract the year
select(-Date) %>% # remove the Date column
group_by(Day) %>% # for each day
summarise_at(vars(matches("V")), ~lm(. ~ Year)$coefficients[2]) # build a model and keep the slope
# # A tibble: 366 x 5
# Day V1 V2 V3 V4
# <chr> <dbl> <dbl> <dbl> <dbl>
# 1 01-01 0.108 0.0554 1.41 3.75
# 2 01-02 -0.0543 -0.103 1.41 3.75
# 3 01-03 -0.143 -0.0176 1.41 3.75
# 4 01-04 0.146 -0.0232 1.41 3.75
# 5 01-05 -0.154 -0.0533 1.41 3.75
# 6 01-06 -0.268 0.0470 1.41 3.75
# 7 01-07 -0.164 0.0873 1.41 3.75
# 8 01-08 0.0634 0.266 1.41 3.75
# 9 01-09 0.0115 -0.0320 1.41 3.75
# 10 01-10 0.0576 -0.237 1.41 3.75
# # ... with 356 more rows
的名称,则可以改用此名称:
v_trend
如果您想了解有关每个线性模型的更多信息,我建议使用一些数据重塑和summarise_at(vars(matches("V")), list(trend = ~lm(. ~ Year)$coefficients[2]))
软件包,如下所示:
broom
然后,您可以查询此数据集并获取所需的任何内容。例如,如果将上述输出另存为library(lubridate)
library(tidyverse)
library(broom)
testframe %>%
mutate(Year = year(Date)) %>%
select(-Date) %>%
gather(v, value, -Day, -Year) %>%
group_by(Day, v) %>%
nest() %>%
mutate(dd = map(data, ~tidy(lm(value ~ Year, data = .)))) %>%
unnest(dd) %>%
arrange(Day)
# # A tibble: 2,928 x 7
# Day v term estimate std.error statistic p.value
# <chr> <chr> <chr> <dbl> <dbl> <dbl> <dbl>
# 1 01-01 V1 (Intercept) -217. 162. -1.34 2.16e- 1
# 2 01-01 V1 Year 0.108 0.0806 1.34 2.16e- 1
# 3 01-01 V2 (Intercept) -112. 196. -0.570 5.84e- 1
# 4 01-01 V2 Year 0.0554 0.0976 0.567 5.86e- 1
# 5 01-01 V3 (Intercept) -2800. 0.260 -10756. 6.25e-30
# 6 01-01 V3 Year 1.41 0.000130 10824. 5.94e-30
# 7 01-01 V4 (Intercept) -7489. 0.694 -10787. 6.11e-30
# 8 01-01 V4 Year 3.75 0.000346 10824. 5.94e-30
# 9 01-02 V1 (Intercept) 109. 238. 0.458 6.59e- 1
# 10 01-02 V1 Year -0.0543 0.119 -0.458 6.59e- 1
# # ... with 2,918 more rows
,则可以按如下方式获得第testframe2
列01-01
的趋势/斜率:
V1
以及该斜率的p值,如下所示:
testframe2 %>% filter(Day == "01-01" & v == "V1" & term == "Year") %>% pull(estimate)