【问题标题】:Reshaping data in crosstab using stack or melt使用堆栈或熔化在交叉表中重塑数据
【发布时间】:2019-11-14 10:51:58
【问题描述】:

我正在处理一个包含 UPC、date_expected 和数量列的数据框。原始数据每天有多个 UPC(每个订单一行,一天内多个订单包含相同的 UPC),但也没有列出每个 UPC 的每个日期,只列出拣货数量大于 0 的日期。 目标:组织一个数据框,显示 UPC 选择的数量,然后按日期预期,列出从 2019 年 5 月 14 日到当前的每个日期,即使数量选择 = 0(显示数量选择 = 0 的行不包括在原始数据源中)。

MFC_order_daily['date_expected'] = pd.to_datetime(MFC_order_daily['date_expected'], format='%Y-%m-%d')
print('Daily Pick Data:')
print(MFC_order_daily)

数据以这种格式传入:

Daily Pick Data:
                 UPC  quantity_picked date_expected
0      0001111041660              1.0    2019-05-14
1      0001111045045              1.0    2019-05-14
             ...              ...           ...
39694  0004470036000              6.0    2019-06-24
39695  0007225001116              1.0    2019-06-24

[39696 rows x 3 columns]

尝试使用 groupby 和 reset_index 进行组织,如下所示,但收到以下数据框缺少数量_picked=0 的日期:

tipd = MFC_order_daily.groupby(['UPC', 'date_expected']).sum().reset_index()
tipd = tipd[['UPC','date_expected','quantity_picked']]
print(tipd)
                 UPC date_expected  quantity_picked
0      0000000002554    2019-05-14              4.0
1      0001111041660    2019-05-14              2.0
2      0001111041660    2019-05-16              2.0
3      0004470036000    2019-05-14              3.0
4      0004470036000    2019-05-16              1.0

然后尝试创建一个交叉表以获取零值并使用堆栈或熔化进行整形。 成功创建并生成交叉表:

tipd2 = pd.crosstab([MFC_order_daily["UPC"]], MFC_order_daily["date_expected"])
print(tipd2)
date_expected  2019-05-14  2019-05-15  ...  2019-06-23  2019-06-24
UPC                                    ...                        
0000000002554           0           0  ...           0           0
0000000003082           0           1  ...           2           3
0000000003107           1           0  ...           2           2
                  ...         ...  ...         ...         ...
0360600051715           0           0  ...           0           0
0501072452748           0           0  ...           0           0
0880100551750           0           0  ...           0           0

[8302 rows x 42 columns]

尝试堆叠:

tipd2.stack('date_expected')
print('Stacked tipd2:')
print(tipd2)

结果数据和上面显示的交叉表一样,没有变化,没有错误。

尝试融化:

tipd2.melt(id_vars=['UPC', 'date_expected'])

产生的错误:

KeyError: "The following 'id_vars' are not present in the DataFrame: ['UPC', 'date_expected']"

期望的输出:

                 UPC date_expected  quantity_picked
0      0000000002554    2019-05-14              4.0
1      0000000002554    2019-05-15              0.0
2      0000000002554    2019-05-16              0.0
3      0001111041660    2019-05-14              2.0
4      0001111041660    2019-05-15              0.0
5      0001111041660    2019-05-16              2.0
6      0004470036000    2019-05-14              3.0
7      0004470036000    2019-05-15              0.0
8      0004470036000    2019-05-16              1.0

为每个 UPC 循环从 19 年 5 月 14 日开始的每个日期。

【问题讨论】:

  • 您确实应该提供一个简短的数据样本以及该样本的预期输出。这样,人们就会更好地理解您想要什么。
  • 你想要df.groupby(['UPC', 'date_expected'])['quantity_picked'].sum().reset_index()吗?
  • @QuangHoang 我试图在不使帖子超载的情况下包含尽可能多的数据。我正在处理大量数据,并试图确保我展示得足够多而不展示太多。 “那个样本”具体是什么意思?我按照模板的建议将预期的输出放在最后。
  • @Erfan 当我尝试得到相同的结果时,我已经得到了。它似乎提供了默认选择的数量总和。唯一的问题是它没有为未选择 UPC 的日期报告 0 值 (quantity_picked=0)。
  • 您期望的输出应该是样本数据的结果。也就是说,人们应该能够在样本数据上运行他们的代码,并将其与预期的输出进行比较。例如,如果你正在寻找数据的总和,你应该给出像1,2,3这样的样本和预期的输出6。你不应该提供像1,2,100,...,1 这样的样本并说你期望100000

标签: python pandas dataframe


【解决方案1】:

IIUC,你可以使用pivotstack

# this is after aggregation by `groupby().sum()`
df = pd.DataFrame({'UPC': ['0000000002554', '0001111041660', '0001111041660', 
                           '0004470036000', '0004470036000'],
 'date_expected': ['2019-05-14',
  '2019-05-14',
  '2019-05-16',
  '2019-05-14',
  '2019-05-16'],
 'quantity_picked': [4.0, 2.0, 2.0, 3.0, 1.0]})


(df.pivot_table(index='UPC', 
          columns='date_expected', 
          values='quantity_picked',
          fill_value=0)
   .stack()
   .reset_index()
)

输出:

             UPC date_expected  0
0  0000000002554    2019-05-14  4
1  0000000002554    2019-05-16  0
2  0001111041660    2019-05-14  2
3  0001111041660    2019-05-16  2
4  0004470036000    2019-05-14  3
5  0004470036000    2019-05-16  1

如果你也想填写日期,那么你可能想看看reindex

【讨论】:

  • 我相信你对 reindex 的建议是正确的,我需要填写日期,所以我想这就是我要找的。当我尝试以下操作时: days = MFC_order_daily['date_expected'].unique() days = pd.to_datetime(days, format='%Y-%m-%d') tipd = MFC_order_daily.groupby(['UPC', 'date_expected']).sum().reindex(days).reset_index() tipd = tipd[['UPC','date_expected','quantity_picked']] print(tipd) 我得到以下错误: TypeError: Argument '元组的类型不正确(预期为 numpy.ndarray,得到 DatetimeArray)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-24
  • 2015-08-22
  • 1970-01-01
  • 2018-04-15
  • 2016-12-18
相关资源
最近更新 更多