当前位置: 首页 > news >正文

极具特色的位置运算

集合在计算机中一般都存储为数组形式,其成员天然会有个位置。数据表本质上是记录的集合,也会被存储成数组,作为成员的记录也有位置的概念。而实际应用中确实有很多分析计算都是位置相关的,但 SQL 把数据表处理成无序集合,就会很不方便。

esProc SPL 保留了数组的有序性,并提供了丰富的位置运算方法,可以用简洁易懂的代码轻松实现这类计算需求。

1. 位置序号

在有序数据集中,记录的位置本身就具有业务意义。比如我们要取某股票 2025 年第 5、10、15、20…交易日的数据。简单的思路是在交易日有序的股票数据中,过滤出 2025 年的记录集合,从中取第 5、10、15、20…条记录就可以了。

无序的 SQL 要用窗口函数临时造出个序号才能完成这样的任务,思路有点“绕”:

SELECT *
FROM (SELECT *,ROW_NUMBER() OVER (ORDER BY date) AS rnFROM stockWHERE YEAR(date) = 2025
)
WHERE rn % 5 = 0;

SPL 支持对记录的位置序号进行计算,可以按照上述简单思路轻松解题:

stock.select(year(date)==2025).select(# % 5==0)

在对数据集循环计算时,# 是当前记录的位置序号。第二个 select 的条件是记录序号 #能被 5 整除,过滤结果自然就是第 5、10、15、20…条记录了。

Python 的源头是常规程序语言,也继承了数组成员位置的概念,相应的代码也较为简洁:

stock_2025 = stock[stock['date'].dt.year == 2025].reset_index(drop=True)
selected_stock = stock_2025[stock_2025.index % 5 == 4]

index 是 Dataframe 对象的默认索引,和 SPL 的 #不同,它是从 0 开始的整数。这个索引是个对象,会占用内存空间。

index 是生成 stock 时自动计算产生的,stock 按年份过滤后必须重置 index,对新的集合重新生成索引,否则 stock_2025.index 得到的还是年份过滤前的位置序号。

而 SPL 中的 #是天然序号,不需要额外的存储空间,也没有重置动作,更加简洁轻便。

Python 还提供了 iloc 函数,能直接用位置取数据:

stock_2025 = stock[stock['date'].dt.year == 2025].reset_index(drop=True)
selected_stock = stock_2025.iloc[4::5]

iloc[4::5] 从整数位置 4(也就是第 5 行)开始,每隔 5 行选取一条数据。

SPL 也可以用类似的方式计算:

stock.select(year(date)==2025).step(5,5)

2. 按条件取位置

条件过滤是常见运算,也就是取得满足一定条件的成员。集合成员有序时,我们有时候还会关心这些满足条件的成员的位置。

比如求某股票上市后,经过多少个交易日涨到了 100 元以上。简单思路是在交易日有序的股票数据中,找出第一个超过 100 元记录的位置序号,就是想要的结果。

SQL 要造个序号,再计算收盘价在 100 元以上记录对应的序号的最小值,思路还是“绕”:

SELECT MIN(rn) 
FROM (SELECT price,ROW_NUMBER() OVER ( ORDER BY date ) rn FROM stock)
WHERE price>100

SPL 则轻松完成任务:

stock.pselect(price > 100)

pselect 是 SPL 基于天然位置序号提供的定位函数,用于获得满足条件成员的位置,这里就是第一个大于 100 元记录的位置序号。

Python 使用 Dataframe 索引写出的代码:

stock [stock['price'] > 100].index[0] + 1

相当于常规过滤后取出索引,略有些繁琐。

单纯取得位置经常并不是目标,我们还要用这个位置做进一步的计算。比如:求股价第一次涨到 100 元以上时的涨幅。自然的思路是:找到第一条收盘价大于 100 元的记录位置,取出这个位置和前一个位置上记录的收盘价,两者相减就可以了。

但是,用 SQL 实现就会“绕”得多了:

WITH T AS (SELECT price,ROW_NUMBER() OVER ( ORDER BY date ) rn,price - LAG(price) OVER ( ORDER BY date) risingFROM Stock)
SELECT Rising FROM T WHERE NO = ( SELECT MIN(rn) FROM T WHERE price>100 )

这要把每天的涨幅都计算出来,CTE 语法生成的中间表也要被遍历两次。

SPL 可以按照自然思路实现,代码非常简捷:

p=stock.pselect(price > 4.5)
stock(p).price-stock(p-1).price

SPL 提供了定位计算函数 calc,可以进一步简化这个代码:

stock.calc(stock.pselect(price>100),price-price[-1])

calc 函数针对 stock.pselect(price>100) 得到的位置,计算表达式 price-price[-1]。SPL 支持跨行计算,price[-1] 表示上一行的收盘价。

Python 有位置概念,也能写出类似的代码:

first_index = stock[stock['price'] > 100].index[0]
result =stock.loc[first_index,'price']- stock.loc[first_index - 1,'price']

不过 Python 没有提供类似 calc 的函数,就只能将 loc 写两次。

3. 取最值位置

有序数据集中,最大、最小值记录所在位置也很有业务意义。

比如求股价第一次达到最高价那天的涨幅。简单思路是在有序的股票数据中,找到第一个达到最高价的记录位置,就很容易解题了。

SQL 写起来还是很麻烦:

WITH T AS (SELECT price,ROW_NUMBER() OVER (ORDER BY date) rn,price - LAG(price) OVER (ORDER BY date) AS risingFROM Stock
),
SELECT rising
FROM T
WHERE price = (SELECT MAX(price) FROM T)
ORDER BY rn
LIMIT 1

窗口函数多,遍历次数多,最后还要先排序再取第一条记录。

SPL 提供了返回最大、最小值出现位置的定位函数 pmax 和 pmin,可以写出非常简捷的代码:

stock.calc(stock.pmax(price ), price - price[-1])

pmax 默认是从前向后找第一个最大值位置序号。

最大值成员可能有多个,假设要找所有最大值对应的涨幅,SPL 这样写:

stock.calc(stock.pmax@a(price ), price - price[-1])

@a 选项可以返回所有这些成员的位置。

Python 的函数 idxmax 也可以返回最大值对应的第一条记录位置:

max_idx = stock['price'].idxmax()
increase = stock.loc[max_idx,'price']- stock.loc[max_idx - 1,'price']

像前面代码一样,需要写两次 loc。

如果取所有最大值对应涨幅,Python 的写法就比较啰嗦了:

max_price = stock['price'].max()
max_idxs = stock[stock['price'] == max_price].index
increase=max_price - stock.loc[max_idxs-1,'price'].values

Python 没有提供返回所有最大值位置的函数,只能先求出最大值,过滤出最大值所在记录,最后用 index 求这些记录的位置。

小结一下:SQL 对付有序集合的位置计算非常麻烦,要临时造序号,思路很绕、代码繁琐。Python 有整数索引,也可以按位置取成员,比 SQL 要方便很多,但索引不够自动化,常常要重置,位置运算也不够丰富,类似任务的实现方法也不一致,较复杂些的任务仍显啰嗦,理解难度也大。SPL 位置运算很独特,有简洁的天然序号,和丰富的定位函数,可以轻松实现此类任务。

esProcSPL是开源免费的,源码地址~

下载试用~

相关文章:

  • 一种通用图片红色印章去除的工具设计
  • ArcGIS Pro 3.4 二次开发 - 布局
  • 最悉心的指导教程——阿里云创建ECS实例教程+Vue+Django前后端的服务器部署(通过宝塔面板)
  • 基于Qt封装数据库基本增删改查操作,支持多线程,并实现SQLite数据库单例访问
  • 系统架构中的组织驱动:康威定律在系统设计中的应用
  • 【连接器专题】SD卡座规格书审查需要审哪些方面?
  • DeepSeek 赋能文化遗产数字化修复:AI 重构千年文明密码
  • 极简以太彩光网络解决方案4.0正式发布,“彩光”重构园区网络极简之道
  • 中国城市间地理距离矩阵(2024)
  • 显卡3080和4060哪个强 两款游戏性能对比
  • AWS Transit Gateway实战:构建DMZ隔离架构,实现可控的网络互通
  • AWS API Gateway 配置WAF(中国区)
  • 云计算Linux Rocky day02(安装Linux系统、设备表示方式、Linux基本操作)
  • 开源协议:构建全球技术协作的基石
  • 通过回调函数注册定时器触发事件
  • Linux线程池(下)(34)
  • 加强LLM防御以实现企业部署
  • 奇异值分解(SVD):线性代数在AI大模型中的核心工具
  • 计算机一次取数过程分析
  • Error: Flash Download failed - Could not load file “xxx.axf“
  • 国外个人网站/天眼查企业查询
  • 黄色视频做爰网站安全/aso安卓优化
  • 企业建设网站风险/西安网络优化培训机构公司
  • 公众号视频网站怎么做/站长工具的使用seo综合查询排名
  • 家居企业网站建设咨询/怎么创建网页
  • 网站建设网址/南昌seo优化