【问题标题】:How to Parallelize python loop with large dataset如何使用大型数据集并行化 python 循环
【发布时间】:2018-05-19 05:21:23
【问题描述】:

我正在尝试在给定数据集的情况下构建层次结构,其中每一行代表一个学生、他们所学的课程以及其他一些元数据。从这个数据集中,我试图构建一个邻接矩阵,并根据学生所选择的课程以及不同学生在选择课程时所采取的路径来确定层次结构。

话虽如此,要构造这个邻接矩阵,计算量很大。这是我目前的代码,已经运行了大约 2 个小时。

uniqueStudentIds = df.Id.unique()
uniqueClasses = df['Course_Title'].unique()
for studentID in uniqueStudentIds:
    for course1 in uniqueClasses:
        for course2 in uniqueClasses:
            if (course1 != course2 and have_taken_both_courses(course1, course2, studentID)):
                x = vertexDict[course1]
                y = vertexDict[course2]
                # Assuming symmetry
                adjacency_matrix[x][y] += 1
                adjacency_matrix[y][x] += 1
                print(course1 + ', ' + course2)


def have_taken_both_courses(course1, course2, studentID):
    hasTakenFirstCourse = len(df.loc[(df['Course_Title'] == course1) & (df['Id'] == studentID)]) > 0
    if hasTakenFirstCourse:
        return len(df.loc[(df['Course_Title'] == course2) & (df['Id'] == studentID)]) > 0
    else:
        return False

鉴于我有一个非常大的数据集大小,我试图在并行化/多线程这个计算上昂贵的 for 循环中查阅在线资源。但是,我是 python 和多处理的新手,所以任何指导将不胜感激!

【问题讨论】:

  • 您最好在 sql 中执行此操作。您只是在寻找所有课程 x, y,这样有一个学生同时参加了 x 和 y?要看的一件事是使用集合而不是列表。它们在查找时速度更快。
  • 虽然我想在 SQL 中执行此操作,但我需要构造矩阵,然后进行一些数据格式化以汇集到 API 中。鉴于我的数据文件是 CSV,我不确定我会如何做到这一点,并且我最终必须返回一个表示图形的 json 对象
  • 您实际上是在对每个唯一对进行线性扫描以获取计数,每次都重复迭代。这:len(df.loc[(df['Course_Title'] == course1) & (df['Id'] == studentID)]) > 0 在您的紧密循环中非常昂贵。并行化不会像更有效地计数那样有帮助。此外,如果您要对唯一 ID 进行 for 循环,只需转换为列表,不要使用 numpy 数组

标签: python pandas parallel-processing multiprocessing


【解决方案1】:

看起来循环的方式比你必须的要多。对于每个学生,您进行 NxN 次迭代,其中 N 是班级总数。但是您的学生只参加了这些课程的一部分。因此,您可以显着减少迭代。

你的 have_taken_both_courses() 查找也比它需要的更昂贵。

这样的事情可能会快很多:

import numpy as np
import itertools
import pandas as pd

df = pd.read_table('/path/to/data.tsv')

students_df = pd.DataFrame(df['student'].unique())
students_lkp = {x[1][0]: x[0] for x in students_df.iterrows()}

classes_df = pd.DataFrame(df['class'].unique())
classes_lkp = {x[1][0]: x[0] for x in classes_df.iterrows()}

df['student_key'] = df['student'].apply(lambda x: students_lkp[x])
df['class_key'] = df['class'].apply(lambda x: classes_lkp[x])

df.set_index(['student_key', 'class_key'], inplace=True)

matr = np.zeros((len(classes_df), len(classes_df)))

for s in range(0, len(students_df)):
    print s
    # get all the classes for this student
    classes = df.loc[s].index.unique().tolist()
    for x, y in itertools.permutations(classes, 2):
        matr[x][y] += 1

【讨论】:

  • 谢谢!这肯定会快很多。只是一些语义上的东西。在底部,x 和 y,这些数字代表什么?
  • 这些是类的代理键。即classes_df中类的索引
  • 当我想在扫描矩阵后检索行的元数据时,给定 class_key 索引我会使用什么命令?
  • classes_df.loc[x] 其中x 是您要查找的键
猜你喜欢
  • 2013-08-28
  • 2021-06-29
  • 1970-01-01
  • 2013-09-02
  • 1970-01-01
  • 2017-12-09
  • 2021-02-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多