我的问题正是这个:
但我希望在 ggplot 中实现公认的答案(如下)。是否可以?
首先我创建一些数据。在这里,我创建了一个 list ,有 5 个 data.frame,有不同的 xs:
ll <- lapply(1:5,function(i)
data.frame(x=seq(i,length.out=10,by=i),y=rnorm(10)))
Run Code Online (Sandbox Code Playgroud)
然后应用大约,我创建了一个包含所有数据的大 data.frame:
big.df <- do.call(rbind,ll)
Run Code Online (Sandbox Code Playgroud)
然后,我绘制线性近似和我所有的系列:
plot(approx(big.df$x,big.df$y),type='l')
lapply(seq_along(ll),
function(i) points(ll[[i]]$x,ll[[i]]$y,col=i))
Run Code Online (Sandbox Code Playgroud)
编辑
我的数据结构(例如,实际 DF 包含 183000 行)
structure(list(timeseries = c(1, 7, 59, 0, 0, 5, 0, 0, 1, 0),
t = c(1, 3, 7, 1, 3, 7, 1, 3, 7, 1)), .Names = c("timeseries",
Run Code Online (Sandbox Code Playgroud)
"t"), row.names = c(NA, 10L), class = "data.frame")
在下面的代码中,我们从您创建的列表开始(根据您的实际数据的样子,可能有更好的方法,但我暂时保持原样)。然后我们使用bind_rows
将其转换为单个数据帧并mutate
添加内插值。我们将它动态提供给 ggplot。geom_line
绘制插值。
内插点是数据中每个 x 值处所有 y 值的精确平均值。为了进行比较,我还添加了geom_smooth
,它使用局部加权回归来绘制数据的平滑曲线。的span
在参数geom_smooth
可以被用于确定平滑量。
library(tidyverse)
theme_set(theme_classic())
# Fake data
set.seed(2)
ll <- lapply(1:5,function(i)
data.frame(x=seq(i,length.out=10,by=i),y=rnorm(10)))
# Combine into single data frame and add interpolation column
bind_rows(ll, .id="source") %>%
mutate(avg = approx(x,y,xout=x)$y) %>%
ggplot(aes(x, y)) +
geom_point(aes(colour=source)) +
geom_line(aes(y=avg)) +
geom_smooth(se=FALSE, colour="red", span=0.3, linetype="11")
Run Code Online (Sandbox Code Playgroud)
现在让我们完成各个数据处理步骤:
从列表中生成单个数据框:
dat = bind_rows(ll, .id="source")
Run Code Online (Sandbox Code Playgroud)
以下是从该数据框中选择的行:
dat[c(1:3, 15:17, 25:27), ]
source x y
1 1 1 -0.896914547
2 1 2 0.184849185
3 1 3 1.587845331
15 2 10 1.782228960
16 2 12 -2.311069085
17 2 14 0.878604581
25 3 15 0.004937777
26 3 18 -2.451706388
27 3 21 0.477237303
Run Code Online (Sandbox Code Playgroud)我们可以得到如下插值:
with(dat, approx(x, y, xout=x))
Run Code Online (Sandbox Code Playgroud)
为了得到 y 值,这是我们上面想要的,我们会这样做:
with(dat, approx(x, y, xout=x))$y
Run Code Online (Sandbox Code Playgroud)
要将 y 值添加到数据框中:
dat$avg = with(dat, approx(x, y, xout=x))
Run Code Online (Sandbox Code Playgroud)为了创建绘图,我们使用dplyr
包中的函数执行数据处理步骤,该tidyverse
包是我们在代码开头加载的包套件的一部分。它包括管道 ( %>%
) 运算符,它允许我们将函数一个接一个地链接起来,并将数据直接输入,ggplot
而不必将中间数据帧分配给对象(当然,如果我们愿意,我们当然可以先创建中间数据帧) )。例如:
dat = bind_rows(ll, .id="source") %>%
mutate(avg = approx(x,y,xout=x)$y)
ggplot(dat, aes(x, y)) +
geom_point(aes(colour=source)) +
geom_line(aes(y=avg)) +
geom_smooth(se=FALSE, colour="red", span=0.3, linetype="11")
Run Code Online (Sandbox Code Playgroud)