繁体   English   中英

Pandas 使用交叉表和自定义列变得独一无二

[英]Pandas get nunique using crosstab and custom columns

我有一个如下所示的数据框

ID,design_id,year,output
1,21345,1978,1
1,3456,2019,1
1,5678,2021,1
1,7890,2021,1
1,5678,2021,2
1,1357,2020,3
2,9876,2021,8
2,9865,2021,1
2,9678,2021,0

我想做以下

a) 创建 4 年列year_2019,year_2020,year_2021 and year_2022

b) 将每个ID的唯一design_id计数放在相应的year列下

我在这篇文章的帮助下尝试了以下两种方法

pd.crosstab(
      index=tf['ID'], columns=tf['year'],
      values=tf['design_id'], aggfunc='nunique').fillna(0)

-------------------------------------

out = (pd
 .crosstab(df['ID'], df['year'])
 .reindex(range(2019, 2022+1), axis=1, fill_value=0)
 .add_prefix('year_')
 .reset_index()
 .rename_axis(columns=None)
)

我的真实数据框有 400 万行,有 50 个独特的年份值。(从 1970 年到 2022 年)

但我想要year2019,2020,2021 and 2022下每个ID的唯一设计 ID 计数(而不是记录计数)。

我希望我的输出如下

ID,year_2019,year_2020,year_2021,year_2022
1,1,1,2,0
2,0,0,3,0

尝试:

y = [2019, 2020, 2021, 2022]


print(
    df[df.year.isin(y)]
    .pivot_table(
        index="ID",
        columns="year",
        values="design_id",
        aggfunc="nunique",
        fill_value=0,
    )
    .reindex(y, axis="columns", fill_value=0)
    .add_prefix("year_")
)

印刷:

year  year_2019  year_2020  year_2021  year_2022
ID                                              
1             1          1          2          0
2             0          0          3          0
df.drop(columns=['output'], inplace=True)
df_grouped = df.groupby(['ID', 'year']).agg('nunique')
final_df = df_grouped.unstack(['year']).fillna(0)

给出final_df作为

     design_id               
year      1978 2019 2020 2021
ID                           
1          1.0  1.0  1.0  2.0
2          0.0  0.0  0.0  3.0

这是否满足您的要求?

根据您指定的解决方案。 您可以按如下方式更改列名

df2=pd.crosstab(
      index=df['ID'], columns=df['year'],
      values=df['design_id'], aggfunc='nunique').fillna(0)
df2.columns = ["year_"+str(col) for col in np.arange(2019,2023)]
df2.reset_index()

    ID  year_2019   year_2020   year_2021   year_2022
0   1      1.0         1.0         1.0        2.0
1   2      0.0         0.0         0.0        3.0

或者

df2=pd.crosstab(
      index=df['ID'], columns=df['year'],
      values=df['design_id'], aggfunc='nunique').fillna(0).add_prefix('year_')
df2
year    year_1978   year_2019   year_2020   year_2021
ID              
1         1.0         1.0         1.0         2.0
2         0.0         0.0         0.0         3.0

这是获得您在问题中要求的结果的一种方法:

y = df[['ID','year','design_id']].drop_duplicates().groupby(['ID','year']).count().unstack(
    fill_value=0).droplevel(0, axis=1).reindex(
    fill_value=0, columns=[2019, 2020, 2021, 2022]).add_prefix('year_').reset_index()
y.columns.name = None

输出:

   ID  year_2019  year_2020  year_2021  year_2022
0   1          1          1          2          0
1   2          0          0          3          0

解释:

  • 在 ID 上使用drop_duplicates() ID, year键和design_id ,然后在 key 的groupby()上使用count()获得所需的计数
  • 使用unstack()使用包含一个或多个ID值的数据的年份创建列
  • 使用droplevel()消除了列 multiindex 的不需要的design_id级别(由 unstack unstack() ) 产生),之后使用reindex()和所需的年份2019, 2020, 2021, 2022add_prefix()创建所需的列标签year_2019, year_2020, year_2021, year_2022以及相应的数据(缺失的地方填零,例如 2022 年)
  • 使用reset_index()ID从索引移动到新列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM