Как вычислить корреляции длинного формата данных с пандами? - PullRequest
0 голосов
/ 23 ноября 2018

У меня есть фрейм данных с 3 столбцами.

UserId | ItemId | Rating

(где рейтинг - это рейтинг, который пользователь присвоил элементу. Это np.float16. 2 идентификатора - np.int32)

Как наилучшим образом вычислить корреляции между элементами с помощью панд Python?

Мне нужно сначала повернуть таблицу (в широком формате), а затем применить pd.corr

df = df.pivot(index='UserId', columns='ItemId', values='Rating')
df.corr()

Он работает с небольшими наборами данных, но не с большими.

На этом первом шаге создается большой набор матричных данных, в основном полный отсутствующих значений.Это довольно интенсивно, и я не могу запустить его с большими фреймами данных.

Нет ли более простого способа вычислить корреляции непосредственно в длинном наборе данных, без поворота?

(я посмотрелв pd.groupBy, но это, кажется, только разбивает фрейм данных, а не то, что я ищу.)

РЕДАКТИРОВАТЬ: упрощенные данные и рабочий сводный код

import pandas as pd
import numpy as np
d = {'UserId': [1,2,3, 1,2,3, 1,2,3], 
     'ItemId': [1,1,1, 2,2,2, 3,3,3], 
     'Rating': [1.1,4.5,7.1, 5.5,3.1,5.5, 1.1,np.nan,2.2]}
df = pd.DataFrame(data=d)
df = df.astype(dtype={'UserId': np.int32, 'ItemId': np.int32, 'Rating': np.float32})
print(df.info())
pivot = df.pivot(index='UserId', columns='ItemId', values='Rating')
print('')
print(pivot)
corr = pivot.corr()
print('')
print(corr)

РЕДАКТИРОВАНИЕ2: Большой случайныйгенератор данных

def randDf(size = 100):
  ## MAKE RANDOM DATAFRAME, df =======================
  import numpy as np
  import pandas as pd
  import random
  import math
  dict_for_df = {}
  for i in ('UserId','ItemId','Rating'):   
    dict_for_df[i] = {}
    for j in range(size):
      if i=='Rating': val = round( random.random()*5, 1) 
      else: val = round( random.random() * math.sqrt(size/2) )
      dict_for_df[i][j] = val     # store in a dict
  # print(dict_for_df)
  df = pd.DataFrame(dict_for_df) # after the loop convert the dict to a dataframe
  # print(df.head())
  df = df.astype(dtype={'UserId': np.int32, 'ItemId': np.int32, 'Rating': np.float32})
  # df = df.astype(dtype={'UserId': np.int64, 'ItemId': np.int64, 'Rating': np.float64})
  ## remove doubles -----
  df.drop_duplicates(subset=['UserId','ItemId'], keep='first', inplace=True)
  ## show -----
  print(df.info())
  print(df.head())
  return df
# =======================

df = randDf()

1 Ответ

0 голосов
/ 27 ноября 2018

У меня был еще один ход, и у меня было что-то, что получает те же числа корреляции, что и ваш метод, без использования pivot, но намного медленнее.Я не могу сказать, использует ли он меньше или больше памяти:

from scipy.stats.stats import pearsonr   
import itertools
import pandas as pd 
import numpy as np

d = []    
itemids = list(set(df['ItemId']))
pairsofitems = list(itertools.combinations(itemids,2))

for itempair in pairsofitems:
    a = df[df['ItemId'] == itempair[0]][['Rating', 'UserId']]
    b = df[df['ItemId'] == itempair[1]][['Rating', 'UserId']]

    z = np.ones(len(set(df.UserId)), dtype=int)
    z = z * np.nan
    z[a.UserId.values] = a.Rating.values

    w = np.ones(len(set(df.UserId)), dtype=int)
    w = w * np.nan
    w[b.UserId.values] = b.Rating.values 

    bad = ~np.logical_or(np.isnan(w), np.isnan(z))
    z = np.compress(bad, z)
    w = np.compress(bad, w)
    d.append({'firstitem': itempair[0], 
              'seconditem': itempair[1], 
              'correlation': pearsonr(z,w)[0]})

df_out = pd.DataFrame(d, columns=['firstitem', 'seconditem', 'correlation'])

Этот был полезен при работе с нянями до получения корреляции.

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

Да, там есть некоторое повторение с переменными z и w, может поместить это в функцию.

Некоторыеобъяснение того, что он делает:

  • найти все комбинации пар в ваших элементах
  • организовать и "x" и "y" набор точек для UserId / Rating, где любая пара точек гдеодин из двух пропущен (нан) отбрасывается.Я думаю о точечной диаграмме, и корреляция заключается в том, насколько хорошо проходит прямая линия.
  • запустите корреляцию Пирсона для этой пары xy
  • , поместите ItemId каждую пару и корреляцию в фрейм данных
...