python - 如何计算长格式数据帧与 Pandas 的相关性?

标签 python pandas dataframe correlation

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

UserId | ItemId | Rating

(其中 Rating 是用户对项目的评分。它是一个 np.float16。2 个 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()

最佳答案

我又试了一次,并且有一些东西可以在不使用数据透视的情况下获得与你的方法完全相同的相关数,但速度要慢得多。我不能说它使用的内存是少了还是多了:

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/Rating 组织和“x”和“y”点集,其中缺少两者之一的任何点对 (nan) 都将被丢弃。我认为散点图和相关性是一条直线穿过它的程度。
  • 在此 x-y 对上运行 PIL 逊相关
  • 将每对的 ItemId 和相关性放入数据框中

关于python - 如何计算长格式数据帧与 Pandas 的相关性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53447658/

相关文章:

r - 将数据分解为每个级别并向其应用函数

python - 多索引pandas数据框,如何获取特定索引的列表

python - AWS Python Lambda 与 Oracle

python - Google App Engine - 发布时运行任务

python - 根据列表更新数据框值

python - 将处理中出现错误的所有行移动到另一个数据帧中?

python - 如何从 Pandas 数据框创建边缘列表?

python - 如何使用 Vim/Emacs 提高工作效率

python - Keras 进度条显示什么?

python - Groupby 用逗号分隔总和