如何计算大格式数据帧与熊猫的相关性?

时间:2018-11-23 13:31:42

标签: python pandas dataframe correlation

我有一个包含3列的数据框。

UserId | ItemId | Rating

(其中Rating是用户对某项产品的评价。它是np.float16。两个ID是np.int32)

如何最好地使用python pandas计算项目之间的相关性

我的想法是先旋转表格(宽格式),然后应用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)

EDIT2:大型随机数据生成器

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 :(得分:0)

我又去了一次,并得到了一些与您的方法完全相同的相关性数字,而没有使用数据透视,但是速度慢得多。我不能说它使用的是更少还是更多的内存:

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'])

This有助于在处理相关性之前解决nan的问题。

for循环之后的两行切片需要时间。但我认为,如果瓶颈能够得到解决,那么它就有潜力。

是的,其中的z和w变量存在一些重复,可以将其放入函数中。

一些解释:

  • 在您的商品中找到对的所有组合
  • 为UserId / Rate组织“ x”和“ x”和“ y”组点,其中缺少其中两个(南)的任何点对将被丢弃。我认为散点图和相关性是一条直线在其中的拟合程度。
  • 对此x-y对运行皮尔逊相关性
  • 将ItemId每对和相关性放入一个数据框