【问题标题】:How to compute the correlations of long format dataframe with pandas?如何计算长格式数据帧与熊猫的相关性?
【发布时间】:2019-04-26 02:57:44
【问题描述】:

我有一个包含 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()

【问题讨论】:

  • 您能否提供一些示例数据和预期输出,并更详细地解释您所说的“项目之间的相关性”是什么意思?您是否有兴趣寻找其中的情况,例如,用户 A 喜欢第 1 项和第 2 项(特定用户对两种不同产品的评分相关)?另外,您总共有多少用户、项目和评分?每个用户是否对每个项目只评分过一次?
  • @PeterLeimbigler 问题中添加的小示例(但不考虑数据类型)。我的数字是约 5 万件商品和约 20 万用户约 2000 万的评分。不,不是“完全”一次:最多一次。 (因此一次或永远)

标签: python pandas dataframe correlation


【解决方案1】:

我又试了一次,在不使用数据透视的情况下,我得到了与你的方法完全相同的相关数字,但速度要慢得多。我不能说它是使用更少还是更多的内存:

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 对上运行 pearson 相关
  • 将每对的 ItemId 和相关性放入一个数据帧中

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-06
    • 1970-01-01
    • 1970-01-01
    • 2017-12-12
    • 1970-01-01
    • 2020-08-02
    • 2017-04-06
    相关资源
    最近更新 更多