이와 같은 데이터 프레임이 있습니다.
>>> import pandas as pd
>>> data = {
'user_id': [1, 1, 1, 2, 2, 3, 3, 4, 4, 4],
'movie_id': [0, 1, 2, 0, 1, 2, 3, 2, 3, 4]
}
>>> df = pd.DataFrame(data)
>>> df
user_id movie_id
0 1 0
1 1 1
2 1 2
3 2 0
4 2 1
5 3 2
6 3 3
7 4 2
8 4 3
9 4 4
첫 번째 영화를 좋아 한 후 두 번째 영화를 좋아하는 사람이 얼마나 될까요? 또는 두 번째 영화를 좋아 한 후 세 번째 영화를 좋아했습니다. Etc. 여기 내 예상 출력이 있습니다.
[[0., 2., 0., 0., 0.],
[0., 0., 1., 0., 0.],
[0., 0., 0., 2., 0.],
[0., 0., 0., 0., 1.],
[0., 0., 0., 0., 0.]]
예를 들어, movie_id=1
그들이 좋아 후 2 번을 좋아 movie_id=0
하므로, matrix[0][1]=2
하고 matrix[1][0]=2
. 좋아, 어떻게이 결과를 찾았습니까? user_id=1
좋아 movie_id=0
, movie_id=1
그리고 movie_id=2
각각에 의해. 또한, user_id=2
좋아 movie_id=0
하고 movie_id=1
각각에 의해. 그래서,matrix[0][1]=2
나는 잘못된 출력을 반환하고 빅 데이터 프레임에서 매우 느리게 작동하는 이것을 시도했습니다.
import numpy as np
item = dict()
def cross(a):
for i in a:
for j in a:
if i == j:
continue
if (i, j) in item.keys():
item[(i, j)] += 1
else:
item[(i, j)] = 1
_ = df.groupby('user_id')['movie_id'].apply(cross)
length = df['movie_id'].nunique()
res = np.zeros([length, length])
for k, v in item.items():
res[k] = v
어떤 생각? 미리 감사드립니다.
다음을 수행 할 수 있습니다.
# add row_numbers as a column
df.reset_index(inplace=True)
# merge df on itself
df2 = df.merge(df, how='inner', on='user_id')
# remove some entries, keep only pairs where movie_id_x was liked before movie_id_y
df2 = df2[df2['index_x']<df2['index_y']].drop(['index_x','index_y'], axis=1)
# use pivot table to make matrix
df3 = df2.pivot_table(index='movie_id_x',columns='movie_id_y', values='user_id', aggfunc='count')
# UPD: add empty rows for movies which were removed
ids = df['movie_id'].unique()
df3 = df3.reindex(ids)
df3 = df3.reindex(ids, axis=1)
df3 = df3.fillna(0)
# convert result from dataframe to array if necessary
res = np.array(df3)
결과:
print(res)
[[0 2 1 0 0]
[0 0 1 0 0]
[0 0 0 2 1]
[0 0 0 0 1]
[0 0 0 0 0]]
아이디어는 행렬이 실제로 희소하고 밀도가 높은 형태로 저장하는 데 많은 메모리가 필요하다는 것입니다 (특히 pandas 데이터 프레임의 형태). 따라서 희소 행렬처럼 저장하는 것이 합리적입니다. 여기에서 접근을 찾았 습니다 .
# add row_numbers as a column
df.reset_index(inplace=True)
# merge df on itself
df2 = df.merge(df, how='inner', on='user_id')
# remove some entries, keep only pairs where movie_id_x was liked before movie_id_y
df2 = df2[df2['index_x']<df2['index_y']].drop(['index_x','index_y'], axis=1)
# use groupby to count movie pairs
df2 = df2.groupby(['movie_id_x','movie_id_y'])['user_id'].count().reset_index()
# create pivot as sparse matrix
movies_t = CategoricalDtype(sorted(df['movie_id'].unique()), ordered=True)
row = df2['movie_id_x'].astype(movies_t).cat.codes
col = df2['movie_id_y'].astype(movies_t).cat.codes
sparse_matrix = csr_matrix((df2["user_id"], (row, col)), \
shape=(movies_t.categories.size, movies_t.categories.size))
# convert sparse to dense if needed
res = sparse_matrix.todense()
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다