对 pandas df 中找到的元组列表中的第一个元素进行排序以便绘制它

Sort first element in list of tuples found in pandas df in order to plot it

我有一个包含 4 列的原始 df:用户(访问网站的用户 ID)、月份(用户访问网站的月份)、年份(用户访问网站的年份)、num_hits(用户访问该网站的次数)那一年的月份。

我想按用户和年份、月份(x 轴)和 num_hits(y 轴)绘制。我在 pandas 中创建了一个元组列表作为列,使用:

df['tup'] = list(zip(df['month'], df['num_hits']))
df1 = df.groupby(['user', 'year'], as_index = False)['tup'].agg(list)

但这就是我卡住的地方,因为我想按第一个元素对 'tup' 列中的元组列表进行排序,这样我就可以绘制这些元组列表中的每一个。我的解决方案是从 df 创建一个列表列表,然后像这样对第一个元素进行排序:

df2 = df1['tup'].values.tolist()
for i in df2: 
    i.sort(key=lambda x: x[0])

然后我可以使用以下方法绘制它们:

for i in range(len(df2)):
    plt.plot(*zip(*df2[i]))

但是通过这样做,我丢失了我想要保留的用户和年份信息,以便将其显示在相应行的图例中。无论如何,是否可以对 pandas df 中的元组列表进行排序,然后使用 matplotlib 直接绘制它,以便我可以在相应行的图例中显示用户和年份?提前谢谢你。

最简单的解决方案是根本不使用元组。您可以创建一个数据透视表 table,其中 useryear 列作为索引,month 列作为列,num_hits 列作为值。通过首先按 month 对行进行排序,列将按正确的顺序排列。通过转置数据框,使 month 现在是索引,而 useryear 是列,您可以简单地调用 .plot() 这将 return 什么你需要:

df.sort_values("month").pivot(index=["user", "year"], columns="month", values="num_hits").T.plot()

如果您愿意,这可以分为几个阶段:

# create the pivot table
df1 = df.sort_values("month").pivot(index=["user", "year"], columns="month", values="num_hits")
# transpose
df2 = df1.T
# plot
df2.plot()

以及我使用的数据,确保月份没有从头开始排序,因此肯定需要更改才能正确:

import pandas as pd
import numpy as np

df = pd.DataFrame({"user": [1]*12*3 + [2]*12*3 + [3]*12*3 + [4]*12*3 + [5]*12*3,
                   "month": list(np.arange(12, 0, -1))*3*5,
                   "year": ([2019]*12 + [2020]*12 + [2021]*12)*5,
                   "num_hits": np.random.randint(0, 1000, 12*3*5)})

尽管据我所见,文档中并未说明,但 .pivot() 似乎无论如何都会对列进行排序,因此您甚至不需要使用 .sort_values().