簡體   English   中英

如何根據日期和兩列的組合將缺失的行添加到 pandas DataFrame?

[英]How can I add missing rows to a pandas DataFrame depending on a date and a combination of two columns?

我有一個場景,其中我有一個包含 4 列的 dataframe:

date, product, store, sales_amt

1/1/2019, A,A,200

1/1/2019,A,B,120

1/2/2019, A,A,75

1/3/2019,A,A,69

1/3/2019,A,B,23

--
--
--

1/31/2019,A,B,49

這些日期應該跨越一整個月(例如,在本例中為 2019 年 1 月),但 dataframe 中有一些缺失的日期。

是否有人對 Python 代碼有任何提示,該代碼可以遍歷特定月份的日期並向 dataframe 添加新行,其中缺少dateproduct / store組合和sales_amt為零?

例如,2019 年 1 月 2 日 A/B 的product / store組合沒有條目。

最后的目標是為每個product / store組合在該月的每一天都有一個條目。

我怎樣才能做到這一點?

set_index之后使用resample

#create a dummy dataframe with data every other day
s=pd.date_range('2019-01-01', '2019-05-01', freq='2D')
df = pd.DataFrame({'Date':s, 'sales_amt':np.random.randint(100,1000,61)})

df.set_index('Date').resample('D').asfreq().fillna(0)

Output:

            sales_amt
Date                 
2019-01-01      996.0
2019-01-02        0.0
2019-01-03      236.0
2019-01-04        0.0
2019-01-05      225.0
...               ...
2019-04-27      444.0
2019-04-28        0.0
2019-04-29      756.0
2019-04-30        0.0
2019-05-01      641.0

我怎樣才能確保每個商店/產品條目都有一個日期條目?

我要使用的技巧是 pivot 需要我缺失值的列組合,然后resample以生成缺失的日期,用 0 填充na並最終重新整形回原始形狀和reset_index

這是一個簡短的腳本來演示這一點:

import pandas as pd
import numpy as np

products = ['tablet', 'laptop', 'phone']
stores = ['downtown', 'subburb', 'supermall']

date_range = pd.date_range('2019-01-01', '2019-03-31')

# create a sample data frame
df = pd.DataFrame({
  'date': date_range,
  'product': np.random.choice(products, len(date_range)),
  'store': np.random.choice(stores, len(date_range)),
  'sales_amt': np.random.normal(50, 10, len(date_range))
})
# remove some dates
df = df[~df.date.isin(['2019-01-10', '2019-01-11', '2019-02-07'])]

# set date as index, pivot product & store, fill na with 0
# reindex & unpivot

shape2 = df.set_index(['date', 'product', 'store']).\
  unstack([1, 2]).\
  resample('D').asfreq().\
  fillna(0).\
  stack([1, 2]).\
  reset_index()

print('%d unique dates in original df' % df['date'].nunique())
print('%d rows in original df' % len(df))
print('%d unique dates after filling missing values' % shape2['date'].nunique())
print('%d rows in after filling missing values' % len(shape2))

shape2.head()

也可以通過left join來做到這一點,首先創建所有所需組合的 dataframe,然后將源數據框left joined 這種方法需要稍長的時間來表達,但對於來自 SQL 思維模式的人來說會更直觀。

cross_product = pd.MultiIndex.from_product([
    pd.date_range(df.date.min(), df.date.max()),
    df['product'].unique(),
    df.store.unique()]
    ).to_frame().\
    reset_index(drop=True).\
    rename({0:'date', 1:'product', 2:'store'}, axis=1)

final_df = cross_product.merge(df, 
    left_on=['date', 'product', 'store'], 
    right_on=['date', 'product', 'store'], 
    how='left').fillna(0)

我相信這可以通過創建整個月的日期索引(在您的情況下是第一個日期和最后一個日期之間的所有日期)然后將其合並到原始 dataframe 上來完成。

因此,如果“df”是包含日期、產品、商店和 sales_amt 的原始 dataframe,那么添加以下代碼應該會有所幫助。

all_dates = pd.DataFrame(pd.date_range(df['date'].min(), df['date'].max()))
all_dates.rename(columns = {0: 'date'}, inplace = True)
df = all_dates.merge(df, on = 'date', how = 'left')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM