分组和引用移位值

时间:2018-04-28 19:56:20

标签: python pandas methods cumulative-sum

我正在尝试跟踪单个商品的库存水平 比较预计的出站和可用性。有几次 预计出站超出可用性的时间和时间 发生我希望Post Available为0.我正在尝试创建 下面有Pre AvailablePost Available列:

 Item  Week  Inbound  Outbound  Pre Available  Post Available 
 A        1      500       200            500             300 
 A        2        0       400            300               0 
 A        3      100         0            100             100 
 B        1       50        50             50               0 
 B        2        0        80              0               0 
 B        3        0        20              0               0 
 B        4       20        20             20               0 

我尝试过以下代码:

def custsum(x):

      total = 0
      for i, v in x.iterrows():
         total += df['Inbound'] - df['Outbound']
         x.loc[i, 'Post Available'] = total
         if total < 0:
            total = 0
      return x

df.groupby('Item').apply(custsum)

但是我收到以下错误消息:

ValueError: Incompatible indexer with Series

我是Python的新手,所以任何帮助都会受到赞赏。 谢谢!

2 个答案:

答案 0 :(得分:2)

不需要自定义功能,您可以使用groupby + shift创建PreAvailable并使用clip(将下边界设置为0){{1} }

PostAvailable

答案 1 :(得分:2)

您可以使用

import numpy as np
import pandas as pd
df = pd.DataFrame({'Inbound': [500, 0, 100, 50, 0, 0, 20],
                   'Item': ['A', 'A', 'A', 'B', 'B', 'B', 'B'],
                   'Outbound': [200, 400, 0, 50, 80, 20, 20],
                   'Week': [1, 2, 3, 1, 2, 3, 4]})
df = df[['Item', 'Week', 'Inbound', 'Outbound']]


def custsum(x):
    total = 0
    for i, v in x.iterrows():
        total += x.loc[i, 'Inbound'] - x.loc[i, 'Outbound']
        if total < 0:
            total = 0
        x.loc[i, 'Post Available'] = total
    x['Pre Available'] = x['Post Available'].shift(1).fillna(0) + x['Inbound']
    return x

result = df.groupby('Item').apply(custsum)
result = result[['Item', 'Week', 'Inbound', 'Outbound', 'Pre Available', 'Post Available']]
print(result)

产生

  Item  Week  Inbound  Outbound  Pre Available  Post Available
0    A     1      500       200          500.0           300.0
1    A     2        0       400          300.0             0.0
2    A     3      100         0          100.0           100.0
3    B     1       50        50           50.0             0.0
4    B     2        0        80            0.0             0.0
5    B     3        0        20            0.0             0.0
6    B     4       20        20           20.0             0.0

此代码与您发布的代码之间的主要区别是:

total += x.loc[i, 'Inbound'] - x.loc[i, 'Outbound']

x.loc用于在i索引的行中选择数字InboundOutbound列。totaltotal += df['Inbound'] - df['Outbound'] 列。所以区别在于数字和total 仍然是数字。相比之下,

ValueError

将整个系列添加到if total < 0: total = 0 。这导致x.loc[i, 'Post Available'] = total之后。 (有关发生这种情况的更多信息,请参阅下文。)

条件

Post
Available

已移至for-loop以上,以确保x['Post Available'] = (df['Inbound'] - df.loc['Outbound']).cumsum() 始终为非负数。

如果您不需要此条件,那么整个cumsum可以替换为

for-loop

由于逐列算术和ValueError: Incompatible indexer with Series 是矢量化操作,因此可以更快地执行计算。 不幸的是,条件阻止我们取消x.loc[i, 'Post Available'] = total 并对计算进行矢量化。

在原始代码中,错误

total

发生在这一行

(i, 'Post Available')

因为(i, 'Post Available')(有时)系列不是简单的数值。熊猫是 尝试将右侧的系列与左侧的索引器(0, 4)对齐。索引器Post Available得到了 转换为(0, 4)之类的元组,因为total是列的列 但是print(total)不是一维系列的合适索引 在右边。

您可以for-looptotal += df['Inbound'] - df['Outbound'] 放入from test import save_data class Worker(QObject): finished = pyqtSignal() # give worker class a finished signal def __init__(self, parent=None): QObject.__init__(self, parent=parent) def do_work(self): save_data.main() self.finished.emit() # emit the finished signal when the loop is done def stop(self): save_data.run = False # set the run condition to false on stop , 或者注意到

的右侧
import time
from Pyqt5.QtCore import pyqtSignal

run = True
value = pyqtSignal(int)

def main():
    x = 1
    while run:
        print(x)
        x += 1
        time.sleep(1)
        #value.emit(x)

是一个系列。