如何在python中为1,5百万用户创建友谊矩阵?



我的任务是创建一个友谊矩阵(用户-用户矩阵(,如果用户是朋友,则值为 1,如果不是,则值为 0。 我的.csv文件有 1,50 万行,所以我创建了以下小 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时,当我想将友谊存储在map中(在for循环中(时,我会出现内存错误。

有什么解决方案吗?

我认为你以错误的方式接近这个问题,你应该尽可能使用pandas和矢量化操作来解释你拥有的大数据。

这是一种完整的pandas方法,具体取决于您的数据。

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对数据进行分块以进行 furthere 优化。

我认为您不应该重复存储字符串。您需要创建一个名称列表并存储名称的索引,而不是名称本身。这部分代码:

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

这样,您就不需要重复存储相同的字符串。

假设你有1000万好友关系,你需要存储10MB的内存。

相关内容