首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >熊猫使用前一时期填充值

熊猫使用前一时期填充值
EN

Stack Overflow用户
提问于 2021-05-01 18:57:08
回答 2查看 414关注 0票数 1

假设数据框架采用以下格式:

几个关于数据的重要注释,数据集非常大,10/百万行,所以解决方案需要缩放。有数千家唯一的商店和数千种独特的产品,每个商店都有多个日期的数据,比简单示例数据集中显示的两个更多。

更新这个原始问题,因为有一些清晰的问题:Pandas fill row values using previous period

代码语言:javascript
复制
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。

这就是我想要的结果:

代码语言:javascript
复制
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
EN

回答 2

Stack Overflow用户

发布于 2021-05-01 20:44:23

我对你的需求和你会收到的数据有一些假设。第一个问题是,您只关心在第一个对象有库存的日期到感兴趣的最后一天之间填写日期(对于我的程序来说,所有商店的日期都是相同的)。第二,商店之间的库存是不一致的,但在某一时间点,所有唯一的库存都是在某一时间点进行的。此外,我还假设有一种可能性,即丢失的股票可以在结束日期之前的某个时间点重新储备。如果这些假设中有任何一个是错误的,那么它们可以很容易地在代码中得到修正。为了便于复制粘贴,整个代码都在下面,下面是一个解释。

代码语言:javascript
复制
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) 

注意:为了简化其余的代码,我将日期更改为整数,但是您可以很容易地添加代码来读取和写入字符串。

代码语言:javascript
复制
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 = []

这将初始化集合,并创建一组存储,以及需要填充库存的最后日期。此外,它还创建一个空列表,该列表将包含将被追加到数据框架的所有缺失行。这是因为熊猫附加比普通的附加慢,所以我们只想做一次,但它是不需要的。

代码语言:javascript
复制
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'])

这些循环确定每个存储区中的唯一项,以及在哪个时间段内它们处于库存状态。

代码语言:javascript
复制
      start_date = min(product_dates)
      need_dates = set(range(start_date,end_date+1))
      missing_dates = need_dates.difference(product_dates)

这就创建了产品应该存在于该商店中的日期集(即使为零)。为了简单起见,我假设日期是连续的,但如果不是这样的话,可以很容易地修正。

代码语言:javascript
复制
      for missing in missing_dates:         
         missing_row = [store,product,0,0,missing]
         all_missing.append(missing_row)

这将在当前商店丢失时将当前产品的0 qty和值添加到当前商店。

代码语言:javascript
复制
missing_frame = pd.DataFrame(all_missing, columns=df.columns)   
df=df.append(missing_frame)  

最后,我们离开了循环,并将所有丢失的数据附加到原始帧中。注意,这显然是不符合规则的,但现在可以将其按所需的配置排序,并在函数中对熊猫进行烘焙。

票数 1
EN

Stack Overflow用户

发布于 2021-05-02 16:05:26

我不知道这段代码在大规模情况下是否有效,但它在最少的操作中完成了工作。

TL;TR

代码语言:javascript
复制
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])
代码语言:javascript
复制
>>> 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

详细信息

  1. 在每个存储中删除所有的最后日期,因为我们从下一步的某一天开始增加日期。日期必须与现有日期的间隔相同。

代码语言:javascript
复制
>>> 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

  1. 增长日期从一天

开始

代码语言:javascript
复制
>>> 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 <- drop

cols)

  • df1中查找在df中不可用的行(基于df)

代码语言:javascript
复制
>>> 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 others

  1. 只保留df (right_only指示器)中不存在的日期:

代码语言:javascript
复制
>>> 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

  1. 合并。

代码语言:javascript
复制
>>> 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

单行版

代码语言:javascript
复制
>>> 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-07
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67349878

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档