Как распараллелить цикл Python с большим набором данных - PullRequest
0 голосов
/ 19 мая 2018

Я пытаюсь построить иерархии на основе набора данных, где каждая строка представляет студента, курс, который они прошли, и некоторые другие метаданные.Из этого набора данных я пытаюсь построить матрицу смежности и определить иерархии, основанные на том, какие классы выбрал учащийся, и на пути, который выбирают разные учащиеся при выборе классов.

При этом, чтобы построить эту смежностьматрица, это вычислительно дорого.Вот код, который у меня есть в настоящее время и который работает около 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

Учитывая, что у меня очень большой размер набора данных, я попытался обратиться к онлайн-ресурсам по распараллеливанию / многопоточности этого вычислительно дорогогодля цикла.Тем не менее, я новичок в Python и многопроцессорности, поэтому любые рекомендации будут с благодарностью!

1 Ответ

0 голосов
/ 19 мая 2018

Похоже, что это намного больше, чем нужно.Для каждого ученика вы делаете 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...