用户项目评分矩阵:IndexError

时间:2018-07-04 10:54:42

标签: python pandas numpy indexoutofboundsexception

我的数据帧urm的形状为(96438,3)

user_id anime_id    user_rating
0   1   20  7.808497
1   3   20  8.000000
2   5   20  6.000000
3   6   20  7.808497
4   10  20  7.808497

我正在尝试建立项目-用户评分矩阵:

X = urm[["user_id", "anime_id"]].as_matrix()
y = urm["user_rating"].values
n_u = len(urm["user_id"].unique())
n_m = len(urm["anime_id"].unique())

R = np.zeros((n_u, n_m))
for idx, row in enumerate(X):
    R[row[0]-1, row[1]-1] = y[idx]

如果代码成功,则矩阵如下所示:(我用0填充了NaN)

Matrix of item_rating-user

在索引user_id中,在列中具有anime_id,并为值定级(我从pivot_table获得了此矩阵)

在某些教程中可以正常工作,但是我有一个

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-278-0e06bd0f3133> in <module>()
     15 R = np.zeros((n_u, n_m))
     16 for idx, row in enumerate(X):
---> 17     R[row[0]-1, row[1]-1] = y[idx]

IndexError: index 5276 is out of bounds for axis 1 with size 5143

2 个答案:

答案 0 :(得分:1)

我假设您具有非连续的用户ID(或电影ID),这意味着存在存在两个索引的索引

  • 没有评分,或者
  • 没有电影

在您的情况下,您假设每个值都是连续的(因为您使用唯一值的数量定义维),因此设置了矩阵维,这会导致一些非连续值超出范围

在这种情况下,您有两个选择:

  • 您可以将矩阵的大小定义为urm["user_id"].max()urm["anime_id"].max()
  • 创建一个字典,将您的值映射到最低的连续值。

第一种方法的缺点显然是它需要您存储更大的矩阵。另外,您可以使用scipy.sparse根据您拥有的数据格式(通常称为coordinate matrix format)创建矩阵。
潜在地,您可以执行以下操作:

from scipy import sparse
# scipy expects the data in (value_column, (x, y))
mat = sparse.coo_matrix((urm["user_rating"], (urm["user_id"], urm["anime_id"]))
# if you want it as a dense matrix
dense_mat = mat.todense()

然后,您也可以按照我先前询问的here

的方式处理第二个建议。

答案 1 :(得分:1)

我尝试了 dennlinger 的第二条建议,它对我有用。 这是我写的代码:

def id_to_index(df):
    """
    maps the values to the lowest consecutive values
    :param df: pandas Dataframe with columns user, item, rating
    :return: pandas Dataframe with the extra columns index_item and index_user
    """

    index_item = np.arange(0, len(df.item.unique()))
    index_user = np.arange(0, len(df.user.unique()))

    df_item_index = pd.DataFrame(df.item.unique(), columns=["item"])
    df_item_index["new_index"] = index_item
    df_user_index = pd.DataFrame(df.user.unique(), columns=["user"])
    df_user_index["new_index"] = index_user

    df["index_item"] = df["item"].map(df_item_index.set_index('item')["new_index"]).fillna(0)
    df["index_user"] = df["user"].map(df_user_index.set_index('user')["new_index"]).fillna(0)


    return df