R中按组进行线性插值
Linear interpolation by group in R
假设有以下数据:
Date V1 V2
1 1996-01-04 0.04383562 days 0.1203920
2 1996-01-04 0.12054795 days 0.1094760
..............
3 1996-02-01 0.04383562 days 0.1081815
4 1996-02-01 0.12054795 days 0.1092450
..............
5 1996-03-01 0.04109589 days 0.1553875
6 1996-03-01 0.13687215 days 0.1469690
对于每个组日期(为了方便,我用点来区分它们),我想做一个简单的线性插值:对于 V1=0.08
我会得到什么 V2
。
我试过的:
首先最合乎逻辑的方法是使用 approx
:
IV<-data %>% group_by(Date) %>% approx(V1,V2,xout=0.08)
但是我得到了这个错误:
Error in approx(., V1, V2, xout = 0.08) :
invalid interpolation method
In addition: Warning message:
In if (is.na(method)) stop("invalid interpolation method") :
the condition has length > 1 and only the first element will be used
然后我尝试了:
Results<-unsplit(lapply(split(data,data$Date),function(x){m<-lm(V2~V1,x)
cbind(x,predict(m,0.08))}),data$Date)
出现错误:
Error in model.frame.default(formula = x[, 3] ~ x[, 2], data = x, drop.unused.levels = TRUE) :
invalid type (list) for variable 'x[, 3]'
我也尝试了 dplyr
包,但没有结果:
IV<-data %>% group_by(Date) %>% predict(lm(V2~V1,data=data,0.08)
给出了错误:
Error in UseMethod("predict") :
no applicable method for 'predict' applied to an object of class "c('grouped_df', 'tbl_df', 'tbl', 'data.frame')"
谢谢。
您在 approx
中遇到的错误是因为您在使用 %>%
时将 data.frame
作为第一个参数传递。所以你的电话是 approx(df, v1, v2, xout=0.08)
.
您可以在一行中使用 data.table
完成 approx
调用:
library(data.table)
#created as df instead of dt for use in dplyr solution later
df <- data.frame(grp=sample(letters[1:2],10,T),
v1=rnorm(10),
v2=rnorm(10))
dt <- data.table(df)
dt[, approx(v1,v2,xout=.08), by=grp]
#output
grp x y
1: b 0.08 -0.5112237
2: a 0.08 -1.4228923
第一次通过 tidyverse
我的解决方案不是很整洁;在管道中可能有更简洁的方法来执行此操作,但我认为很难击败 data.table
解决方案。
强制进入 magrittr
管道的解决方案:
library(dplyr)
df %>%
group_by(grp) %>%
summarise(out=list(approx(v1,v2,xout=.08))) %>%
ungroup() %>%
mutate(x=purrr::map_dbl(out,'x'),
y=purrr::map_dbl(out,'y')) %>%
select(-out)
#output
# A tibble: 2 × 3
grp x y
<fctr> <dbl> <dbl>
1 a 0.08 -1.4228923
2 b 0.08 -0.5112237
假设有以下数据:
Date V1 V2
1 1996-01-04 0.04383562 days 0.1203920
2 1996-01-04 0.12054795 days 0.1094760
..............
3 1996-02-01 0.04383562 days 0.1081815
4 1996-02-01 0.12054795 days 0.1092450
..............
5 1996-03-01 0.04109589 days 0.1553875
6 1996-03-01 0.13687215 days 0.1469690
对于每个组日期(为了方便,我用点来区分它们),我想做一个简单的线性插值:对于 V1=0.08
我会得到什么 V2
。
我试过的:
首先最合乎逻辑的方法是使用 approx
:
IV<-data %>% group_by(Date) %>% approx(V1,V2,xout=0.08)
但是我得到了这个错误:
Error in approx(., V1, V2, xout = 0.08) :
invalid interpolation method
In addition: Warning message:
In if (is.na(method)) stop("invalid interpolation method") :
the condition has length > 1 and only the first element will be used
然后我尝试了:
Results<-unsplit(lapply(split(data,data$Date),function(x){m<-lm(V2~V1,x)
cbind(x,predict(m,0.08))}),data$Date)
出现错误:
Error in model.frame.default(formula = x[, 3] ~ x[, 2], data = x, drop.unused.levels = TRUE) :
invalid type (list) for variable 'x[, 3]'
我也尝试了 dplyr
包,但没有结果:
IV<-data %>% group_by(Date) %>% predict(lm(V2~V1,data=data,0.08)
给出了错误:
Error in UseMethod("predict") :
no applicable method for 'predict' applied to an object of class "c('grouped_df', 'tbl_df', 'tbl', 'data.frame')"
谢谢。
您在 approx
中遇到的错误是因为您在使用 %>%
时将 data.frame
作为第一个参数传递。所以你的电话是 approx(df, v1, v2, xout=0.08)
.
您可以在一行中使用 data.table
完成 approx
调用:
library(data.table)
#created as df instead of dt for use in dplyr solution later
df <- data.frame(grp=sample(letters[1:2],10,T),
v1=rnorm(10),
v2=rnorm(10))
dt <- data.table(df)
dt[, approx(v1,v2,xout=.08), by=grp]
#output
grp x y
1: b 0.08 -0.5112237
2: a 0.08 -1.4228923
第一次通过 tidyverse
我的解决方案不是很整洁;在管道中可能有更简洁的方法来执行此操作,但我认为很难击败 data.table
解决方案。
强制进入 magrittr
管道的解决方案:
library(dplyr)
df %>%
group_by(grp) %>%
summarise(out=list(approx(v1,v2,xout=.08))) %>%
ungroup() %>%
mutate(x=purrr::map_dbl(out,'x'),
y=purrr::map_dbl(out,'y')) %>%
select(-out)
#output
# A tibble: 2 × 3
grp x y
<fctr> <dbl> <dbl>
1 a 0.08 -1.4228923
2 b 0.08 -0.5112237