Как создать матрицу дружбы для 1,5 миллиона пользователей в python? - PullRequest
0 голосов
/ 23 октября 2018

Моя задача - создать матрицу дружбы (матрица пользователь-пользователь), значения которой равны 1, если пользователи являются друзьями, и 0, если нет.Мой файл .csv содержит 1,5 миллиона строк, поэтому я создаю следующий маленький CSV для проверки моего алгоритма:

user_id              friends
   Elena          Peter, John
   Peter          Elena, John
   John           Elena, Peter, Chris
   Chris          John

Для этого маленького CSV мой код работает хорошо:

%matplotlib inline

import pandas as pd
import seaborn as sns
import numpy as np

from scipy import sparse

sns.set(style="darkgrid")

user_filepath = 'H:\\YelpData\\test.csv' # this is my little test file

df = pd.read_csv(user_filepath, usecols=['user_id','friends'])

def Convert_String_To_List(string):
    if string!="None":
        li = list(string.split(", ")) 
    else:
        li = []
    return li 

friend_map = {}

for i in range(len(df)): #storing friendships in map
    friend_map[df['user_id'][i]] = Convert_String_To_List(df['friends'][i])

users = sorted(friend_map.keys()) 
user_indices = dict(zip(users, range(len(users)))) #giving indices for users

#and now the sparsity matrix:

row_ind = [] #row indices, where the value is 1
col_ind = [] #col indices, where the value is 1
data = []    # value 1

for user in users:
    for barat in baratok[user]:
        row_ind.append(user_indices[user])
        col_ind.append(user_indices[barat])

for i in range(len(row_ind)):
    data.append(1)

mat_coo = sparse.coo_matrix((data, (row_ind, col_ind)))

friend_matrix = mat_coo.toarray() #this friendship matrix is good for the little csv file

Но когда я пробую этот код на моем большом (1,5 миллиона строк) CSV, я получаю ошибку памяти, когда я хочу сохранить дружбу на карте (в цикле for).

Есть ли какое-то решение дляэто?

Ответы [ 2 ]

0 голосов
/ 23 октября 2018

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

Это полный pandas подход в зависимости от вашегоdata.

import pandas as pd

_series = df1.friends.apply(lambda x: pd.Series(x.split(', '))).unstack().dropna()
data = pd.Series(_series.values, index=_series.index.droplevel(0))
pd.get_dummies(data).groupby('user_id').sum()

Вывод

        Chris   Elena   John    Peter
user_id             
Chris   0          0    1        0
Elena   0          0    1        1
John    1          1    0        1
Peter   0          1    1        0

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

0 голосов
/ 23 октября 2018

Я думаю, вы не должны хранить строку повторно.Вам необходимо составить список имен и сохранить индекс имени, а не само имя.Эта часть кода:

friend_map[df['user_id'][i]] = Convert_String_To_List(df['friends'][i])

может быть изменена.Если у вас есть список пользователей,

users = [....] # read from csv
friend_list = Convert_String_To_List(df['friends'][i])
friend_list_idxs = Get_Idx_of_Friends(users,friend_list) #look up table users
friend_map[df['user_id'][i]] = friend_list_idxs

Таким образом, вам не нужно будет повторно хранить одну и ту же строку.

Допустим, у вас есть 10 миллионов отношений с друзьями, вам нужно будет сохранить10 МБ памяти.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...