创建数据透视表以计算项目一起出现在列表中的次数

2024-10-01 09:39:07 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图计算用户在同一会话中查看页面的次数

我从一个数据框开始,列出用户ID和他们访问过的页面段塞:

user_id page_view_page_slug
1       slug1
1       slug2
1       slug3
1       slug4
2       slug5
2       slug3
2       slug2
2       slug1

我希望得到的是一个数据透视表,它计算slug横截面的用户ID

^{tb1}$

我意识到当我们看到slug1和slug2与slug2和slug1时,这将是相同的数据反映,但我想不出更好的方法。 到目前为止,我已经做了一个列表

def listagg(df, grouping_idx):
    return df.groupby(grouping_idx).agg(list)
new_df = listagg(df,'user_id')

返回:

          page_view_page_slug
user_id                                                   
1        [slug1, slug2, slug3, slug4]
2        [slug5, slug3, slug2, slug2]
7        [slug6, slug4, slug7]
9        [slug3, slug5, slug1]

但我很难想到当项目同时出现在一个列表中时(不管顺序如何)循环计数,以及如何存储它。然后我也不知道如何将其转换为可透视格式


Tags: 数据用户viewiddfpage页面slug
3条回答

让我们试试groupbyreduce

from functools import reduce

dfs = [pd.DataFrame(1, index=list(s), columns=list(s)) 
      for _, s in df.groupby('user_id')['page_view_page_slug']]
      
df_out = reduce(lambda x, y: x.add(y, fill_value=0), dfs).fillna(0).astype(int)

详细信息:

^{}user_id上的数据帧,然后为page_view_page_slug中的每个组创建一个邻接数据帧,其索引和列对应于该组中的slugs

>>> dfs

[       slug1  slug2  slug3  slug4
 slug1      1      1      1      1
 slug2      1      1      1      1
 slug3      1      1      1      1
 slug4      1      1      1      1,
        slug5  slug3  slug2  slug1
 slug5      1      1      1      1
 slug3      1      1      1      1
 slug2      1      1      1      1
 slug1      1      1      1      1]

现在^{}使用带有可选参数fill_value=0的缩减函数^{}来计算上述邻接数据帧,以便计算段塞横截面的用户id

>>> df_out

       slug1  slug2  slug3  slug4  slug5
slug1      2      2      2      1      1
slug2      2      2      2      1      1
slug3      2      2      2      1      1
slug4      1      1      1      1      0
slug5      1      1      1      0      1

可选地您可以将上述代码包装到函数中,如下所示:

def count():
    df_out = pd.DataFrame()
    for _, s in df.groupby('user_id')['page_view_page_slug']:
        df_out = df_out.add(
            pd.DataFrame(1, index=list(s), columns=list(s)), fill_value=0)

    return df_out.fillna(0).astype(int)

>>> count()

       slug1  slug2  slug3  slug4  slug5
slug1      2      2      2      1      1
slug2      2      2      2      1      1
slug3      2      2      2      1      1
slug4      1      1      1      1      0
slug5      1      1      1      0      1

让我们对具有mergepd.crosstab的用户id使用自联接进行计数:

import pandas as pd
from io import StringIO

txt = StringIO("""user_id  page_view_page_slug
1       slug1
1       slug2
1       slug3
1       slug4
2       slug5
2       slug3
2       slug2
2       slug1""")

df = pd.read_csv(txt, sep='\s\s+')

dfm = df.merge(df, on='user_id')
df_out = pd.crosstab(dfm['page_view_page_slug_x'], dfm['page_view_page_slug_y'])

df_out

输出:

page_view_page_slug_y  slug1  slug2  slug3  slug4  slug5
page_view_page_slug_x                                   
slug1                      2      2      2      1      1
slug2                      2      2      2      1      1
slug3                      2      2      2      1      1
slug4                      1      1      1      1      0
slug5                      1      1      1      0      1

对于重复数据,让我们尝试:

dfi = df.assign(v_count=df.groupby(['user_id', 'page_view_page_slug']).cumcount())

#Let's filter some unnecessary joins with query
dfi = dfi.merge(dfi, on=['user_id'])\
         .query('page_view_page_slug_x != page_view_page_slug_y or page_view_page_slug_x == page_view_page_slug_y and v_count_x == v_count_y')

df_out = pd.crosstab(dfi['page_view_page_slug_x'], dfi['page_view_page_slug_y'])
df_out

输出:

page_view_page_slug_y  slug1  slug2  slug3  slug4  slug5
page_view_page_slug_x                                   
slug1                      3      3      3      2      1
slug2                      3      2      2      1      1
slug3                      3      2      2      1      1
slug4                      2      1      1      1      0
slug5                      1      1      1      0      1

这里是另一种方法,使用numpy广播创建一个矩阵,该矩阵是通过将{}中的每个值与每个其他值进行比较获得的,然后从该矩阵创建一个新的数据帧,其中{}和{}设置为{},并沿着{}和{}对{}进行计数段塞的横截面:

a = df['user_id'].values
i = list(df['page_view_page_slug'])

pd.DataFrame(a[:, None] == a, index=i, columns=i)\
   .sum(level=0).sum(level=0, axis=1).astype(int)

       slug1  slug2  slug3  slug4  slug5
slug1      2      2      2      1      1
slug2      2      2      2      1      1
slug3      2      2      2      1      1
slug4      1      1      1      1      0
slug5      1      1      1      0      1

相关问题 更多 >