匡醍量化|大富翁量化

Pandas Alternatives: Modin, Polars, Dask for Quant Data

中文 📅 2025-04-05 👁 views this month —

“Modin accelerates Pandas operations via multi-core parallelism, reading 10GB CSV files 4-8x faster; Polars, built on Rust, uses only 1/3 of Pandas’ memory; Dask supports distributed computing, easily handling TB-scale data.”


1.4. Using eval or query

The query method resembles the WHERE clause in SQL, allowing string expressions for more concise code. For example, df.query('Q1 > Q2 > 90') is supported, along with introducing external variables using the @ symbol. For instance, filtering data points above the average after calculating the mean. Similarly, the eval method returns a boolean index, which must be used with df[], such as: df[df.eval("Q1 > 90 > Q3 >10")].

The isin method filters values in a column that exist in a specified list. For example, b1["类别"].isin(["能源","电器"]) filters the category column. Additionally, multiple conditions can be combined, such as: df[df['ucity'].isin(['广州市','深圳'])].

1.4.1. The query() Function: SQL-Style Conditional Filtering

  1. Core Syntax
df.query('表达式')  # 表达式需用引号包裹,支持逻辑运算符和列名直接引用
  1. Financial Scenario Example
"""案例1:筛选特定股票代码的高额交易"""
# 筛选AAPL或TSLA股票,且金额超过100万的交易
df.query("symbol in ['AAPL', 'TSLA'] and amount > 1e6")

"""案例2:动态引用外部变量"""
avg_amount = df['amount'].mean()  # 计算平均交易金额
df.query("amount > @avg_amount * 2")  # 筛选金额超过平均2倍的交易[3,5](@ref)

"""案例3:多条件组合"""
# 筛选2025年Q1买入且成交价高于开盘价的交易
df.query("trade_type == 'buy' and trade_date >= '2025-01-01' and price > open_price")
  1. Performance Advantages
  • Expression optimization: Accelerated by the numexpr library at the底层 (underlying) level, it is over 30% faster than traditional boolean indexing.
  • Column name handling: Column names containing spaces or special characters must be wrapped in backticks (e.g., `收盘价` > 100).

1.4.2. The eval() Function: Expression-Based Boolean Indexing

  1. Core Syntax
mask = df.eval("表达式")  # 返回布尔数组
df[mask]  # 用布尔索引筛选数据
  1. Financial Scenario Example
"""案例1:计算复杂交易条件"""
# 筛选波动率超过阈值且交易量增长的股票
df[df.eval("(high - low)/close > 0.05 and volume > volume.shift(1)")]

"""案例2:动态公式计算"""
# 筛选夏普比率高于行业平均的基金
industry_avg = 1.2
df[df.eval("(returns - risk_free_rate)/std_dev > @industry_avg")]
  1. Difference from query()
    • eval() returns a boolean array and must be used with df[]; query() directly returns the filtered DataFrame.
    • Both share the same expression engine, so performance differences are negligible. Choose based on code conciseness.

1.4.3. The isin() Function: Multi-Value Matching Filtering

  1. Core Syntax
df[df['列名'].isin(值列表)]  # 筛选列值存在于列表中的行
  1. Financial Scenario Example
"""案例1:筛选特定股票池"""
blue_chips = ['600519.SH', '000858.SZ', '601318.SH']  # 上证50成分股
df[df['symbol'].isin(blue_chips)]

"""案例2:排除ST/ST风险股"""
risk_stocks = ['*ST长生', 'ST康美']  
df[~df['stock_name'].isin(risk_stocks)]  # 使用~取反[2](@ref)

"""案例3:联合多列筛选"""
# 筛选沪深300且行业为科技或金融的股票
target_industries = ['Technology', 'Financials']
df[df['index'].isin(['000300.SH']) & df['industry'].isin(target_industries)]
  1. Advanced Usage
    • Dictionary filtering: Joint matching across multiple columns (e.g., df[df.isin({'symbol':'AAPL', 'exchange':'NASDAQ'})]).
    • Performance optimization: For large lists (>10,000 elements), converting to a set() first is recommended to improve speed.

1.4.4. Comprehensive Performance Optimization Strategies

  1. Filter Before Calculating

# 错误:先计算全量再筛选
df['return'] = df['close'].pct_change()  
df_filtered = df[df['volume'] > 1e6]

# 正确:先筛选减少计算量
df_filtered = df[df['volume'] > 1e6].copy()  
df_filtered['return'] = df_filtered['close'].pct_change()[6](@ref)
  1. Avoid Chained Operations
# 错误:两次索引降低性能
df[df['symbol'] == 'AAPL']['close']  
# 正确:单次loc操作
df.loc[df['symbol'] == 'AAPL', 'close'][3](@ref)
  1. Type Optimization
# 将字符串列转为category提升isin速度
df['symbol'] = df['symbol'].astype('category')[8](@ref)

1.4.5. Method Comparison and Applicable Scenarios

Method Applicable Scenario Performance Advantage
query() Complex multi-condition combinations, dynamic variable references Expression optimization acceleration
eval() Generating intermediate boolean indices for subsequent processing Performance close to query()
isin() Rapid matching of discrete value lists (e.g., stock codes) Set acceleration + type optimization

Practical Recommendations:

  • High-frequency filtering: Prioritize query() to maintain code conciseness.

  • Large lists: Use isin() with set types to improve speed.
  • Dynamic calculations: eval() is suitable for embedding mathematical formulas or cross-column operations.

1.5. Other Pandas Alternatives

1.5.1. Modin: Single-Machine Multi-Core Parallel Accelerator

One line of code to replace Pandas, providing multi-core, memory-unlimited computing power.

  1. Core Principles

    • Parallelization: Splits Pandas DataFrames into multiple partitions, utilizing multi-core CPUs for parallel processing, with underlying support for Ray or Dask engines.
    • Syntax Compatibility: Only requires modifying the import statement (import modin.pandas as pd) to seamlessly replace native Pandas, supporting over 90% of common APIs.
  2. Performance Advantages

    • Reading Acceleration: Reading 10GB CSV files is 4-8x faster than Pandas.
    • Calculation Optimization: Aggregation operations like groupby are 3-5x faster on 4-core machines, with memory usage reduced by 30%.
    • Applicable Scenarios: Processing datasets from 100MB to 50GB in single-machine environments, suitable for financial high-frequency trading log analysis and user behavior data cleaning.
  3. Usage Case

# 读取大规模交易数据(并行加速)
import modin.pandas as pd
df = pd.read_csv("trades.csv", parse_dates=["timestamp"])

# 实时计算每分钟交易量
volume_by_minute = df.groupby(pd.Grouper(key="timestamp", freq="T"))["amount"].sum().compute()
  1. Precautions
    • Small Dataset Disadvantage: Processing data <100MB may be slower than Pandas due to startup overhead.
    • Memory Consumption: Requires reserving 2-3x the data size in memory to avoid Out Of Memory (OOM) errors.

1.5.2. Polars: Rust-Driven High-Speed Engine

The fastest table solution.

  1. Core Principles

    • Rust + Arrow Architecture: Based on the Rust language and Apache Arrow memory format, supporting zero-copy data processing and SIMD instruction optimization.
    • Multi-threading and Lazy Execution: Automatically parallelizes calculations, optimizing query plans through lazy execution via lazy().
  2. Performance Advantages

    • Speed Comparison: 5-10x faster than Pandas for equivalent operations; 100 million row groupby calculations take only 11 seconds (Pandas takes 187 seconds).
    • Memory Efficiency: Memory usage is only 1/3 of Pandas, supporting out-of-core computation when memory is insufficient.
  3. Applicable Scenarios

    • High-Frequency Financial Data: Such as real-time volatility calculation and order book snapshot analysis.
    • Complex Aggregations: Multi-condition statistics, time-window rolling calculations (e.g., VWAP).
  4. Code Example


import polars as pl
# 惰性执行优化查询
df = pl.scan_csv("market_data.csv")
result = (
   df.filter(pl.col("price") > 100)
   .groupby("symbol")
   .agg([pl.col("volume").sum(), pl.col("price").mean()])
   .collect()  # 触发计算
)

Tip

Precautions - Syntax Differences: Some Pandas methods need rewriting (e.g., `df[df.col > 0]` → `df.filter(pl.col("col") > 0)`). - Visualization Compatibility: Must be converted to Pandas or NumPy to use Matplotlib/seaborn.
#### 1.5.3. Dask: The Swiss Army Knife for Distributed Computing _Distributed table processing, runnable on thousands of nodes._
  1. Core Principles
    • Distributed Task Scheduling: Splits tasks into DAGs (Directed Acyclic Graphs), supporting single-machine multi-core or cluster distributed execution.
    • Out-of-Core Computation: Processes datasets exceeding memory limits through partitioning (e.g., TB-scale logs).

  1. Performance Advantages

    • Horizontal Scaling: Processing 50GB data on a 16-core machine is 10x faster than Pandas, with support for scaling to thousand-node clusters.
    • Ecosystem Compatibility: Seamlessly integrates with libraries like XGBoost and Dask-ML, supporting distributed model training.
  2. Applicable Scenarios

    • Ultra-Large Scale Data: Such as full-market historical行情 (market data) analysis and social network graph calculations.
    • ETL Pipelines: Multi-step data cleaning and feature engineering (requires dependency management).
  3. Practical Tips

    import dask.dataframe as dd
    # Read and process in chunks
    ddf = dd.read_csv("s3://bucket/large_file_*.csv", blocksize="256MB")
    # Parallel calculation of annualized volatility for each stock
    volatility = ddf.groupby("symbol")["return"].std().compute()

Tip

Precautions - Debugging Complexity: Requires using the Dask Dashboard to monitor task status and identify data skew issues. - Configuration Optimization: Reasonably set partition sizes (recommended 100MB~1GB) to avoid scheduling overhead.
---

1.5.4. Selection Decision Tree

Scenario Recommended Tool Reason
Single-Machine Medium Data (<50GB) Modin Zero-code modification, quickly improves existing Pandas script performance
High-Frequency Calculation / Memory-Constrained Polars Extreme speed and low memory consumption, suitable for quantitative trading scenarios
Distributed / Ultra-Large Data (>1TB) Dask Supports cluster scaling, complete ecosystem

Note: Actual testing shows that Polars leads in single-machine performance, while Dask is more advantageous in distributed scenarios. It is recommended to choose comprehensively based on data scale and hardware resources.