R中的算法在保持等级顺序的同时平滑向量
Algorithm in R to smooth out a vector while retaining rank order
我需要编写一个函数来平滑向量而不丢失向量值的原始排序。我想出的是以下内容:
#1 Sort all values of vector in ascending order
#2 for the kth value in vector s_k in the ordered list, collect the list of 2N+1 values in the window of values between [s_{k-N}, s_{k+N}]
#3 by definition, s_k is the median of the values in that window
#4 replace s_k with the mean of value in that same window for all values of k
理想情况下,我希望能够编写一个依赖于 dbplyr
的函数,因为我正在处理远程数据,但这不是绝对必要的,因为我可以将数据分成块,所以基础 R 也可以。同样,这也可以是所有 postgressql 代码或 paritial sql partial dbplyr
并且它们是一样的,但有一些要求。我需要能够参数化 N
并且我需要能够为函数提供一个数据帧列表或一组表(如果在数据库中)以循环遍历(在 R 中这很简单,一个带有lapply
包装器内 N
的单个参数)。
这是我到目前为止 N=3
的结果:
#Example Data
s <- rnorm(1000, mean=50, sd=10)
test.in <- as.data.frame(s)
test.in$id <- 1:length(s)
#Non parameterized attempt
test.out <- test.in %>%
rename(s = union_v_corporate_candidate) %>%
mutate(lag_k_3 = lag(s, 3),
lead_k_3 = lead(s, 3),
lag_k_2 = lag(s, 2),
lead_k_2 = lead(s, 2),
lag_k_1 = lag(s, 1),
lead_k_1 = lead(s, 1)) %>%
mutate(window_mean = (lag_k_3 + lead_k_3 + lag_k_2 + lead_k_2 + lag_k_1 + lead_k_1 + s)/7) %>%
select(id, s, window_mean)
上述方法的逻辑问题是我无法参数化 N
,因为每个额外的 N
值都需要两个额外的 mutate 子句。
您要找的是 SQL 中的 Window 个框架。我引用自 this and this link。在 SQL 中,这样的命令可能如下所示:
SELECT Col1
,Col2
,SUM(Col2) OVER(ORDER BY Col1 ROWS BETWEEN N PRECEDING AND N FOLLOWING) AS window_sum
FROM db.table
其中N
是从当前行向前看和向后看多少行的参数。所以上面的命令产生 2N+1
行移动总和。
在 dbplyr 中,此功能由 window_order
和 window_frame
提供。官方参考 here and an alternative here.
根据他们的示例,您可能需要如下内容:
N = 3
test_out = test_in %>%
group_by(id) %>% # find the moving mean for each group separately
window_order(s) %>% # how should your data be sorted (think 'arrange') often date
window_frame(-N, N) %>% # set width of window
mutate(window_mean = mean(s))
# check SQL produced
sql_build(test_out)
# or
show_query(test_out)
我强烈建议您检查结果 SQL 以确保您的 R 代码按照您的想法运行。
我需要编写一个函数来平滑向量而不丢失向量值的原始排序。我想出的是以下内容:
#1 Sort all values of vector in ascending order
#2 for the kth value in vector s_k in the ordered list, collect the list of 2N+1 values in the window of values between [s_{k-N}, s_{k+N}]
#3 by definition, s_k is the median of the values in that window
#4 replace s_k with the mean of value in that same window for all values of k
理想情况下,我希望能够编写一个依赖于 dbplyr
的函数,因为我正在处理远程数据,但这不是绝对必要的,因为我可以将数据分成块,所以基础 R 也可以。同样,这也可以是所有 postgressql 代码或 paritial sql partial dbplyr
并且它们是一样的,但有一些要求。我需要能够参数化 N
并且我需要能够为函数提供一个数据帧列表或一组表(如果在数据库中)以循环遍历(在 R 中这很简单,一个带有lapply
包装器内 N
的单个参数)。
这是我到目前为止 N=3
的结果:
#Example Data
s <- rnorm(1000, mean=50, sd=10)
test.in <- as.data.frame(s)
test.in$id <- 1:length(s)
#Non parameterized attempt
test.out <- test.in %>%
rename(s = union_v_corporate_candidate) %>%
mutate(lag_k_3 = lag(s, 3),
lead_k_3 = lead(s, 3),
lag_k_2 = lag(s, 2),
lead_k_2 = lead(s, 2),
lag_k_1 = lag(s, 1),
lead_k_1 = lead(s, 1)) %>%
mutate(window_mean = (lag_k_3 + lead_k_3 + lag_k_2 + lead_k_2 + lag_k_1 + lead_k_1 + s)/7) %>%
select(id, s, window_mean)
上述方法的逻辑问题是我无法参数化 N
,因为每个额外的 N
值都需要两个额外的 mutate 子句。
您要找的是 SQL 中的 Window 个框架。我引用自 this and this link。在 SQL 中,这样的命令可能如下所示:
SELECT Col1
,Col2
,SUM(Col2) OVER(ORDER BY Col1 ROWS BETWEEN N PRECEDING AND N FOLLOWING) AS window_sum
FROM db.table
其中N
是从当前行向前看和向后看多少行的参数。所以上面的命令产生 2N+1
行移动总和。
在 dbplyr 中,此功能由 window_order
和 window_frame
提供。官方参考 here and an alternative here.
根据他们的示例,您可能需要如下内容:
N = 3
test_out = test_in %>%
group_by(id) %>% # find the moving mean for each group separately
window_order(s) %>% # how should your data be sorted (think 'arrange') often date
window_frame(-N, N) %>% # set width of window
mutate(window_mean = mean(s))
# check SQL produced
sql_build(test_out)
# or
show_query(test_out)
我强烈建议您检查结果 SQL 以确保您的 R 代码按照您的想法运行。