You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用rollify计算percent_rank时出现维度不匹配错误的排查

问题描述

数据结构

我有结构如下的Wide_DF表格(实际行数更多):

DATETICKERTotal_Put
2021-01-03A23.4
2021-01-03B13.1
2021-01-03C34.6

其中TICKER字段包含A、B、C三个取值,每个标的对应全量日期数据,日期按降序排列。

需求

新增第4列,计算Total_Put基于最近60个值的百分位排名。

实现代码

rankCalc <- tibbletime::rollify( ~percent_rank(.x), window = 60)

Wide_DF = Wide_DF %>%
          dplyr::group_by(TICKER) %>%
          dplyr::mutate(ROW_VALUE = rankCalc(Total_Put )) %>%
          dplyr::ungroup()

错误信息

Error in dplyr::mutate():
ℹ In argument: ROW_VALUE=rankCalc(Total_Put ).
ℹ In group 1: TICKER = "A".
Caused by error:
! ROW_VALUE must be size 1060 or 1, not 60119.

看起来是窗口大小导致的错误,但将percent_rank替换为mean时代码可正常运行,且Wide_DF仅有3000行,请问可能的错误原因是什么?


问题原因与解决方案

核心原因

tibbletime::rollify要求传入的函数必须返回单个值,但dplyr::percent_rank()是对整个输入向量计算每个元素的百分位排名,返回的是和输入长度相同的向量,而不是窗口内的单个值——这就导致每次滚动窗口计算时,都会输出60个值,最终叠加后总长度远超分组后的行数,触发维度不匹配错误。

而mean()这类聚合函数是对窗口向量返回单个值,所以能正常运行。

解决方法

需要自定义一个函数,对每个滚动窗口的向量计算当前窗口内最后一个元素的百分位排名,或者直接计算窗口内每个元素的相对排名后取对应位置的值。这里提供两种可行方案:

方案1:自定义窗口内百分位排名函数

# 自定义函数:计算窗口向量中最后一个元素的百分位排名
roll_percent_rank <- function(x) {
  if (length(x) < 2) return(NA)
  # 计算窗口内所有值的百分位排名,取最后一个元素的结果
  dplyr::percent_rank(x)[length(x)]
}

# 用rollify包装该函数
rankCalc <- tibbletime::rollify(roll_percent_rank, window = 60)

Wide_DF <- Wide_DF %>%
  dplyr::group_by(TICKER) %>%
  dplyr::mutate(ROW_VALUE = rankCalc(Total_Put)) %>%
  dplyr::ungroup()

方案2:使用slider包替代(更灵活)

如果可以安装slider包,它的滚动计算接口更直观,支持自定义窗口逻辑:

library(slider)

Wide_DF <- Wide_DF %>%
  dplyr::group_by(TICKER) %>%
  dplyr::mutate(ROW_VALUE = slide_dbl(
    Total_Put,
    ~dplyr::percent_rank(.x)[length(.x)],
    .before = 59,  # 最近60个值包含当前行,所以向前取59个
    .complete = TRUE  # 仅当窗口有60个值时计算,否则返回NA
  )) %>%
  dplyr::ungroup()

补充说明

因为你的日期是降序排列,slide_dbl的.before=59会取当前行及之前的59行,正好是最近60个值,符合需求;如果需要包含未来的行,可调整.after参数。

内容的提问来源于stack exchange,提问作者Siddharth Somani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 01:13:36