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

使用arrange、groupby与索引计算百分比变动的相关疑问

library(crypto2)
library(dplyr)

coins = crypto_list(only_active = TRUE)

coins = coins[(coins$symbol %in% c("BTC","ETH")),]

thirteen.months.data = crypto_history(coins, start_date=Sys.Date() - (13 * 30))

mydf <- thirteen.months.data[substr(thirteen.months.data$timestamp,1,10) %in% as.character((Sys.Date()-c(1,31,366))),] %>% 
  select(timestamp,name,close,market_cap) %>% 
  arrange(name,timestamp) %>% 
  as.data.frame

# Present
df1  <- mydf %>% group_by(name) %>% slice(3) %>% select(-1)

# M-o-M growth
df2  <- mydf %>% group_by(name) %>% summarise(m.o.m  = (close[3]-close[2])/close[2]*100)

# Y-o-Y growth
df3 <- mydf %>% group_by(name) %>% summarise(y.o.y = (close[3]-close[1])/close[1]*100)

问题1:arrange排序后执行group_by,是否会打乱之前的排序结果?

不会。dplyr的group_by()仅负责按指定变量分组,不会修改每个分组内部的行顺序,组内的行排列会完全继承arrange()后的排序结果。你这里先按name和timestamp升序排列,分组后每个币种(BTC/ETH)的组内数据依然保持timestamp从小到大的顺序,这也是后续能通过索引取对应时间点数据的基础。

问题2:计算M-oM、Y-oY的逻辑是否符合预期?group_by后用close[2]这类索引是否允许?

逻辑是否符合预期?

符合。从你的筛选逻辑来看,mydf里每个币种对应三个时间点的数据:Sys.Date()-366(去年同期)、Sys.Date()-31(上月同期)、Sys.Date()-1(昨日),经过arrange(name, timestamp)后,每个分组内的close顺序是「去年→上月→昨日」。

  • M-o-M(月环比)计算的是(昨日收盘价 - 上月收盘价)/上月收盘价×100,逻辑正确;
  • Y-o-Y(同比)计算的是(昨日收盘价 - 去年收盘价)/去年收盘价×100,逻辑也符合预期。

索引方式是否允许?

允许,但有前提:每个分组必须恰好有3行数据(你的代码里通过日期筛选保证了这一点,所以当前场景下没问题)。如果某个分组的行数不等于3,这种索引方式会返回NA或者报错。

不过更推荐用dplyr原生的nth()函数来替代直接索引,可读性更强,也更贴合dplyr的语法风格,修改后的代码如下:

# M-o-M growth(优化后)
df2  <- mydf %>% group_by(name) %>% summarise(m.o.m  = (nth(close,3)-nth(close,2))/nth(close,2)*100)

# Y-o-Y growth(优化后)
df3 <- mydf %>% group_by(name) %>% summarise(y.o.y = (nth(close,3)-nth(close,1))/nth(close,1)*100)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 23:15:49