假设数据框架采用以下格式:
几个关于数据的重要注释,数据集非常大,10/百万行,所以解决方案需要缩放。有数千家唯一的商店和数千种独特的产品,每个商店都有多个日期的数据,比简单示例数据集中显示的两个更多。
更新这个原始问题,因为有一些清晰的问题:Pandas fill row values using previous period
d = {'store': ['s1', 's1', 's1', 's2', 's2', 's2'], 'product': ['a', 'a', 'b', 'c', 'b', 'b'], 'amount': [1, 2, 3, 5, 2, 3],'value': [1, 2, 3, 5, 2, 3], 'date': ['2020-6-6', '2020-6-7', '2020-6-7',
'2020-6-6', '2020-6-6','2020-6-7']}
df = pd.DataFrame(data=d)
print(df)
store product amount value date
0 s1 a 1 1 2020-6-6
1 s1 a 2 2 2020-6-7
2 s1 b 3 3 2020-6-7
3 s2 c 5 5 2020-6-6
4 s2 b 2 2 2020-6-6
5 s2 b 3 3 2020-6-7对于商店S2,产品c在2020年-6-7日不再存在,我希望能够计算出每种产品数量的百分比变化或差异。
例如:df‘.diff’=df.groupby(‘商店’,‘产品’)‘For’..diff()
但是,为了使其有效,并显示c的差值为-3和-100%,c将需要在下一个日期出现,其金额设置为0。
这就是我想要的结果:
print(df)
store product amount value date
0 s1 a 1 1 2020-6-6
1 s1 a 2 2 2020-6-7
2 s1 b 3 3 2020-6-7
3 s2 c 5 5 2020-6-6
4 s2 b 2 2 2020-6-6
5 s2 b 3 3 2020-6-7
6 s2 c 0 0 2020-6-7发布于 2021-05-01 20:44:23
我对你的需求和你会收到的数据有一些假设。第一个问题是,您只关心在第一个对象有库存的日期到感兴趣的最后一天之间填写日期(对于我的程序来说,所有商店的日期都是相同的)。第二,商店之间的库存是不一致的,但在某一时间点,所有唯一的库存都是在某一时间点进行的。此外,我还假设有一种可能性,即丢失的股票可以在结束日期之前的某个时间点重新储备。如果这些假设中有任何一个是错误的,那么它们可以很容易地在代码中得到修正。为了便于复制粘贴,整个代码都在下面,下面是一个解释。
d = {'store': ['s1', 's1', 's1', 's2', 's2', 's2'], 'product': ['a', 'a', 'b', 'c', 'b', 'b'], 'amount': [1, 2, 3, 5, 2, 3],'value': [1, 2, 3, 5, 2, 3], 'date': [6, 7, 7, 6, 6, 7]}
df = pd.DataFrame(data=d)
store_set = set(df['store'])
end_date = end_date = max(df['date'])
all_missing = []
for store in store_set:
store_rows=df.loc[df['store'] == store]
inventory = set(store_rows['product'])
for product in inventory:
product_rows=df.loc[df['product'] == product]
product_dates = set(product_rows['date'])
start_date = min(product_dates)
need_dates = set(range(start_date,end_date+1))
missing_dates = need_dates.difference(product_dates)
for missing in missing_dates:
missing_row = [store,product,0,0,missing]
all_missing.append(missing_row)
missing_frame = pd.DataFrame(all_missing, columns=df.columns)
df=df.append(missing_frame) 注意:为了简化其余的代码,我将日期更改为整数,但是您可以很容易地添加代码来读取和写入字符串。
d = {'store': ['s1', 's1', 's1', 's2', 's2', 's2'], 'product': ['a', 'a', 'b', 'c', 'b', 'b'], 'amount': [1, 2, 3, 5, 2, 3],'value': [1, 2, 3, 5, 2, 3], 'date': [6, 7, 7, 6, 6, 7]}
df = pd.DataFrame(data=d)
store_set = set(df['store'])
end_date = end_date = max(df['date'])
all_missing = []这将初始化集合,并创建一组存储,以及需要填充库存的最后日期。此外,它还创建一个空列表,该列表将包含将被追加到数据框架的所有缺失行。这是因为熊猫附加比普通的附加慢,所以我们只想做一次,但它是不需要的。
for store in store_set:
store_rows=df.loc[df['store'] == store]
inventory = set(store_rows['product'])
for product in inventory:
product_rows=df.loc[df['product'] == product]
product_dates = set(product_rows['date'])这些循环确定每个存储区中的唯一项,以及在哪个时间段内它们处于库存状态。
start_date = min(product_dates)
need_dates = set(range(start_date,end_date+1))
missing_dates = need_dates.difference(product_dates)这就创建了产品应该存在于该商店中的日期集(即使为零)。为了简单起见,我假设日期是连续的,但如果不是这样的话,可以很容易地修正。
for missing in missing_dates:
missing_row = [store,product,0,0,missing]
all_missing.append(missing_row)这将在当前商店丢失时将当前产品的0 qty和值添加到当前商店。
missing_frame = pd.DataFrame(all_missing, columns=df.columns)
df=df.append(missing_frame) 最后,我们离开了循环,并将所有丢失的数据附加到原始帧中。注意,这显然是不符合规则的,但现在可以将其按所需的配置排序,并在函数中对熊猫进行烘焙。
发布于 2021-05-02 16:05:26
我不知道这段代码在大规模情况下是否有效,但它在最少的操作中完成了工作。
TL;TR
cols = ["store", "product", "date"]
df1 = df[df.groupby("store")["date"].apply(lambda store: store < store.max())]
df1 = df1.assign(amount=0, value=0, date=df["date"]+pd.DateOffset(days=1))
df1 = df[cols].merge(df1, on=cols, how="outer", indicator=True)
df1 = df1.loc[lambda x: x["_merge"] == "right_only"].drop(columns="_merge")
out = pd.concat([df, df1])>>> out
store product amount value date
0 s1 a 1.0 1.0 2020-06-06
1 s1 a 2.0 2.0 2020-06-07
2 s1 b 3.0 3.0 2020-06-07
3 s2 c 5.0 5.0 2020-06-06
4 s2 b 2.0 2.0 2020-06-06
5 s2 b 3.0 3.0 2020-06-07
6 s2 c 0.0 0.0 2020-06-07详细信息
>>> df1 = df[df.groupby("store")["date"].apply(lambda store: store < store.max())]
store product amount value date
0 s1 a 1 1 2020-06-06
3 s2 c 5 5 2020-06-06
4 s2 b 2 2 2020-06-06开始
>>> df1 = df1.assign(amount=0, value=0, date=df["date"]+pd.DateOffset(days=1))
store product amount value date
0 s1 a 0 0 2020-06-07 # date already exist in df <- drop
3 s2 c 0 0 2020-06-07 # missing date in df <- keep
4 s2 b 0 0 2020-06-07 # date already exist in df <- dropcols)
df1中查找在df中不可用的行(基于df)>>> df1 = df[cols].merge(df1, on=cols, how="outer", indicator=True)
store product date amount value _merge
0 s1 a 2020-06-06 NaN NaN left_only
1 s1 a 2020-06-07 0.0 0.0 both
2 s1 b 2020-06-07 NaN NaN left_only
3 s2 c 2020-06-06 NaN NaN left_only
4 s2 b 2020-06-06 NaN NaN left_only
5 s2 b 2020-06-07 0.0 0.0 both
6 s2 c 2020-06-07 0.0 0.0 right_only # keep it, drop othersdf (right_only指示器)中不存在的日期:>>> df1 = df1.loc[lambda x: x["_merge"] == "right_only"].drop(columns="_merge")
store product date amount value
6 s2 c 2020-06-07 0.0 0.0最后,将两个dataframes df1和
>>> out = pd.concat([df, df1])
store product amount value date
0 s1 a 1.0 1.0 2020-06-06
1 s1 a 2.0 2.0 2020-06-07
2 s1 b 3.0 3.0 2020-06-07
3 s2 c 5.0 5.0 2020-06-06
4 s2 b 2.0 2.0 2020-06-06
5 s2 b 3.0 3.0 2020-06-07
6 s2 c 0.0 0.0 2020-06-07单行版
>>> pd.concat([df, df[cols].merge(df[df.groupby("store")["date"] \
.apply(lambda store: store < store.max())] \
.assign(amount=0, value=0, date=df["date"]+pd.DateOffset(days=1)),
on=cols, how="outer", indicator=True) \
.loc[lambda x: x["_merge"] == "right_only"] \
.drop(columns="_merge")])
store product amount value date
0 s1 a 1.0 1.0 2020-06-06
1 s1 a 2.0 2.0 2020-06-07
2 s1 b 3.0 3.0 2020-06-07
3 s2 c 5.0 5.0 2020-06-06
4 s2 b 2.0 2.0 2020-06-06
5 s2 b 3.0 3.0 2020-06-07
6 s2 c 0.0 0.0 2020-06-07https://stackoverflow.com/questions/67349878
复制相似问题