对数据框的所有列进行插值或样条化

Interpolating or spline all columns of a data frame

如果一个数据框有 M 行,如何对其进行插值或样条化以创建一个具有 N 行的新数据框?这是一个例子:

# Start with some vectors of constant length (M=7) with data at each time point t
df <- tibble(t = c(1, 2, 3, 4, 5, 6, 7),
             y1 = c(0.0, 0.5, 1.0, 3.0, 5.0, 2.0, 0.0),
             y2 = c(0.0, 0.75, 1.5, 3.5, 6.0, 4.0, 0.0),
             y3 = c(0.0, 1.0, 2.0, 4.0, 3.0, 2.0, 0.0))

# How to interpolate or spline these to other numbers of points (rows)?
# By individual column, to spline results to a new vector with length N=15:
spline(x=df$t, y=df$y1, n=15)
spline(x=df$t, y=df$y2, n=15)
spline(x=df$t, y=df$y3, n=15)

所以通过矢量这是微不足道的。问题是,如何将此样条应用于具有 M 行的数据集中的所有列以创建具有 N 行的新数据集,最好使用 tidyverse 方法,例如:

df15 <- df %>% mutate(...replace(?)...(spline(x=?, y=?, n=15)... ???))

同样,我希望将此样条应用于所有列,而不必指定包含列名的语法。目的是将其应用于具有大约 100 列的数据框,并且列的名称和数量可能会有所不同。如果可以简化方法,当然没有必要在数据框中包含 t(或 x)列。感谢您的任何见解。

splinereturn一个list。因此,我们可以用 summarise 循环 across,然后 unpack 列(summarise 可以灵活地 returning 任意数量的行,而 mutate是固定的,即它应该 return 与输入相同的行数)

library(dplyr)
library(tidyr)
library(stringr)
df %>%
   summarise(across(y1:y3,  ~spline(t, .x, n = 15) %>%
    as_tibble %>% 
    rename_with(~ str_c(cur_column(), .)))) %>% 
   unpack(everything())

-输出

# A tibble: 15 × 6
     y1x   y1y   y2x   y2y   y3x   y3y
   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
 1  1    0      1    0      1    0    
 2  1.43 0.319  1.43 0.404  1.43 0.542
 3  1.86 0.468  1.86 0.673  1.86 0.905
 4  2.29 0.566  2.29 0.907  2.29 1.18 
 5  2.71 0.752  2.71 1.21   2.71 1.56 
 6  3.14 1.18   3.14 1.68   3.14 2.30 
 7  3.57 1.93   3.57 2.43   3.57 3.33 
 8  4    3      4    3.5    4    4    
 9  4.43 4.24   4.43 4.84   4.43 3.83 
10  4.86 4.99   4.86 5.85   4.86 3.21 
11  5.29 4.56   5.29 5.90   5.29 2.67 
12  5.71 3.12   5.71 4.96   5.71 2.29 
13  6.14 1.47   6.14 3.46   6.14 1.82 
14  6.57 0.269  6.57 1.74   6.57 1.09 
15  7    0      7    0      7    0    

注意:在这里,我们重命名了列,因为 spline 的输出是 list,名称为 xydata.frame/tibble 想要唯一列名

这里有一个选项data.table

library(data.table)

setDT(df)[,
  lapply(.SD, function(v) list2DF(spline(t, v, n = 15))),
  .SDcols = patterns("^y\d+")
]

这给出了

        y1.x      y1.y     y2.x      y2.y     y3.x      y3.y
 1: 1.000000 0.0000000 1.000000 0.0000000 1.000000 0.0000000
 2: 1.428571 0.3194303 1.428571 0.4039226 1.428571 0.5423159
 3: 1.857143 0.4680242 1.857143 0.6731712 1.857143 0.9052687
 4: 2.285714 0.5655593 2.285714 0.9065841 2.285714 1.1770242
 5: 2.714286 0.7515972 2.714286 1.2081346 2.714286 1.5555866
 6: 3.142857 1.1773997 3.142857 1.6848330 3.142857 2.3039184
 7: 3.571429 1.9306220 3.571429 2.4271800 3.571429 3.3318454
 8: 4.000000 3.0000000 4.000000 3.5000000 4.000000 4.0000000
 9: 4.428571 4.2387392 4.428571 4.8368010 4.428571 3.8340703
10: 4.857143 4.9919616 4.857143 5.8546581 4.857143 3.2089361
11: 5.285714 4.5551878 5.285714 5.8976389 5.285714 2.6706702
12: 5.714286 3.1239451 5.714286 4.9619776 5.714286 2.2875045
13: 6.142857 1.4724741 6.142857 3.4632587 6.142857 1.8204137
14: 6.571429 0.2685633 6.571429 1.7399284 6.571429 1.0868916
15: 7.000000 0.0000000 7.000000 0.0000000 7.000000 0.0000000