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

优化Reddit子社区共同用户数计算:多CSV重复读取提速方案

优化Reddit社区共同用户统计效率的方案

核心优化思路

因为要处理数十亿次两两对比,预处理+内存缓存是提升速度的关键,你的排序思路完全可行,以下是具体落地步骤:

1. 预处理阶段:一次性完成所有清洗与结构化

  • 批量处理所有49000个sub的CSV:
    • 移除机器人账号(从removal_users.csv中过滤)
    • 筛选karma>30的用户
    • 将每个sub的有效用户列表按用户名排序后保存为二进制格式(比如pickle或feather),或者直接缓存到内存中的有序列表
    • 不要按karma排序,按用户名排序才是对求交集有帮助的排序方式——有序列表可以用双指针法比集合交集更快,且内存占用更可控

2. 内存缓存策略

既然内存无限制,直接把所有预处理后的用户列表(有序)加载到内存字典中:sub_name -> sorted_user_list,这样每次对比无需重复读CSV,直接从内存取数据,彻底消除IO瓶颈。

3. 高效求交集的两种方案

方案A:双指针法(基于有序列表)

排序后的用户列表可用双指针遍历,时间复杂度O(n+m),比集合交集的哈希开销更低,适合大规模数据:

def count_common_sorted(list1, list2):
    count = 0
    i = j = 0
    len1, len2 = len(list1), len(list2)
    while i < len1 and j < len2:
        if list1[i] == list2[j]:
            count += 1
            i += 1
            j += 1
        elif list1[i] < list2[j]:
            i += 1
        else:
            j += 1
    return count

方案B:预存为哈希集合(内存充足时)

如果内存完全无压力,直接把每个sub的用户列表转为frozenset(不可变,节省内存),交集计算用len(set1 & set2),代码更简洁,哈希查找的O(1)特性也能保证速度。

4. 原代码的即时优化点

  • 原代码中同时用dt.fread和pd.read_csv读取同一个文件,完全冗余,删掉其中一个(推荐用datatable.fread,读取速度远快于pandas)
  • drops = remove_list['C0'].to_list()[0]存在逻辑错误,应该取整个列的列表:drops = remove_list['C0'].to_list()
  • 预处理时一次性完成过滤,避免每次对比都重复执行过滤逻辑

预处理代码示例

import pandas as pd
import pickle
from pathlib import Path

# 加载机器人列表
remove_list = pd.read_csv('D:/Spring 2023/red/c7/removal_users.csv', header=None)
drops = remove_list[0].tolist()

# 预处理所有sub文件
sub_data = {}
sub_dir = Path('D:/Spring 2023/red/sub_csvs')  # 替换为你的sub CSV目录

for csv_path in sub_dir.glob('*.csv'):
    # 读取文件(用datatable更快,这里用pandas示例)
    sub_df = pd.read_csv(csv_path, header=None, names=['user', 'score', 'comment_count'])
    # 过滤机器人和低karma用户
    filtered = sub_df[~sub_df['user'].isin(drops) & (sub_df['score'] > 30)]
    # 按用户名排序
    sorted_users = filtered['user'].sort_values().tolist()
    # 获取sub名称
    sub_name = csv_path.stem.split('.')[0]
    # 存入内存字典,同时可选保存为pickle备用
    sub_data[sub_name] = sorted_users
    with open(f'./preprocessed/{sub_name}.pkl', 'wb') as f:
        pickle.dump(sorted_users, f)

# 批量对比示例
def batch_compare(sub_data):
    sub_names = list(sub_data.keys())
    results = {}
    for i in range(len(sub_names)):
        for j in range(i+1, len(sub_names)):
            sub1 = sub_names[i]
            sub2 = sub_names[j]
            common_count = count_common_sorted(sub_data[sub1], sub_data[sub2])
            results[(sub1, sub2)] = common_count
    return results

关键结论

  • 优先做预处理+内存缓存,这是消除重复IO和过滤操作的核心,能带来数量级的速度提升
  • 用户名排序后用双指针法求交集,是大规模数据下比集合交集更高效的选择
  • 不要按karma排序,对求交集无帮助,按用户名排序才是正确方向

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 10:32:29