【问题标题】:How to calculate by column and stop at certain condition?如何按列计算并在特定条件下停止?
【发布时间】:2020-11-11 06:41:38
【问题描述】:

我在下面有dataframe

import pandas as pd

data = pd.DataFrame({
        'ID':  ['27459', '27459', '27459', '27459', '27459', '27459', '27459', '48002', '48002', '48002'],
        'Invoice_Date': ['2020-06-26', '2020-06-29', '2020-06-30', '2020-07-14', '2020-07-25', 
                         '2020-07-30', '2020-08-02', '2020-05-13', '2020-06-20', '2020-06-28'],
        'Payment_Term': [7,8,3,6,4,7,8,5,3,6],
        'Payment_Date': ['2020-07-05', '2020-07-05','2020-07-03', '2020-07-21', '2020-07-31', 
                         '2020-08-15', '2020-08-22', '2020-06-16', '2020-06-23', '2020-07-05'],
        })

df = pd.DataFrame(data, columns = ['ID', 'Invoice_Date', 'Payment_Term', 'Payment_Date'])

df['Invoice_Date'] = pd.to_datetime(df['Invoice_Date'].astype(str), format='%Y-%m-%d')
df['Payment_Date'] = pd.to_datetime(df['Payment_Date'].astype(str), format='%Y-%m-%d')
df['Due_Date'] = df['Invoice_Date'] + pd.to_timedelta(df['Payment_Term'], unit = 'd') 
df['Delay'] = df['Payment_Date'] - df['Due_Date']
df['Delay'] = df['Delay'].dt.days                                                
df['diff'] = df.groupby('ID')['Invoice_Date'].diff() / np.timedelta64(1, 'D')
df['diff'] = df['diff'].fillna(0)
df

我需要使days 列停止在 30 并开始计算新的。 为难,days 应该基于 group by ID 计算。我以前用过:

df.loc[0, 'days'] = df.loc[0, 'diff']

for i in range(1, len(df)):
    df.loc[i, 'days'] = df.loc[i-1, 'days'] + df.loc[i, 'diff']
    
print(df)

因此输出:

      ID Invoice_Date  Payment_Term Payment_Date   Due_Date  Delay  diff  days
0  27459   2020-06-26             7   2020-07-05 2020-07-03      2   0.0   0.0
1  27459   2020-06-29             8   2020-07-05 2020-07-07     -2   3.0   3.0
2  27459   2020-06-30             3   2020-07-03 2020-07-03      0   1.0   4.0
3  27459   2020-07-14             6   2020-07-21 2020-07-20      1  14.0  18.0
4  27459   2020-07-25             4   2020-07-31 2020-07-29      2  11.0  29.0
5  27459   2020-07-30             7   2020-08-15 2020-08-06      9   5.0  34.0
6  27459   2020-08-02             8   2020-08-22 2020-08-10     12   3.0  37.0
7  48002   2020-05-13             5   2020-06-16 2020-05-18     29   0.0  37.0
8  48002   2020-06-20             3   2020-06-23 2020-06-23      0  38.0  75.0
9  48002   2020-06-28             6   2020-07-05 2020-07-04      1   8.0  83.0

我需要的结果是:

      ID Invoice_Date  Payment_Term Payment_Date   Due_Date  Delay  diff  days
0  27459   2020-06-26             7   2020-07-05 2020-07-03      2   0.0   0.0
1  27459   2020-06-29             8   2020-07-05 2020-07-07     -2   3.0   3.0
2  27459   2020-06-30             3   2020-07-03 2020-07-03      0   1.0   4.0
3  27459   2020-07-14             6   2020-07-21 2020-07-20      1  14.0  18.0
4  27459   2020-07-25             4   2020-07-31 2020-07-29      2  11.0  29.0
5  27459   2020-07-30             7   2020-08-15 2020-08-06      9   5.0   0.0
6  27459   2020-08-02             8   2020-08-22 2020-08-10     12   3.0   8.0
7  48002   2020-05-13             5   2020-06-16 2020-05-18     29   0.0   0.0
8  48002   2020-06-20             3   2020-06-23 2020-06-23      0  38.0   0.0
9  48002   2020-06-28             6   2020-07-05 2020-07-04      1   8.0   0.0

不同之处在于第 4 行停止的天数总和,因为当它添加到下一行时,它将大于 30。因此,它在第 5 行开始新的计算。

【问题讨论】:

  • 您所要做的就是添加两个标志来检查 id 是否与上面的行相同并检查值是否小于 30。将这些标志添加到您的循环中。如果 flag 为 false,则重新开始计算

标签: python pandas loops for-loop


【解决方案1】:

它仍然无法捕获您正在寻找的确切输出,因为即使没有总和(例如索引 8),一些相​​应的 diff 值也大于 30,因此它们将保留在数据上。

def func(x):
    x = x.values
    values = [x[0]]
    for i in range(1, len(x)):
        value = values[i-1] + x[i]
        values.append(value if value < 30 else x[i])
    return values

df['days'] = df.groupby("ID")["diff"].transform(func)
print(df[['ID', 'diff', 'days']])

输出:

      ID  diff  days
0  27459   0.0   0.0
1  27459   3.0   3.0
2  27459   1.0   4.0
3  27459  14.0  18.0
4  27459  11.0  29.0
5  27459   5.0   5.0
6  27459   3.0   8.0
7  48002   0.0   0.0
8  48002  38.0  38.0
9  48002   8.0   8.0

编辑:

更改函数定义应该可以工作:

def func(x):
    x = x.values
    values = [x[0]]
    for i in range(1, len(x)):
        value = values[i-1] + x[i]
        if value < 30:
            values.append(value)
        elif x[i] >= 30:
            values.append(x[i-1])
        else:
            values.append(x[i])
    return values

df['days'] = df.groupby("ID")["diff"].transform(func)
print(df[['ID', 'diff', 'days']])

      ID  diff  days
0  27459   0.0   0.0
1  27459   3.0   3.0
2  27459   1.0   4.0
3  27459  14.0  18.0
4  27459  11.0  29.0
5  27459   5.0   5.0
6  27459   3.0   8.0
7  48002   0.0   0.0
8  48002  38.0   0.0
9  48002   8.0   8.0

【讨论】:

  • 嗨@Cainã Max Couto-Silva。这段代码工作得很好。但是,在第 8 行,它应该开始新的计算,因为它超过了 30 天。
  • 我在编辑后的答案中添加了一个修改后的函数。它应该可以工作,但要确保它对您的数据/分析有意义。
猜你喜欢
  • 2018-03-09
  • 1970-01-01
  • 1970-01-01
  • 2022-10-19
  • 2018-09-11
  • 2019-12-17
  • 2020-07-03
  • 2016-09-04
  • 1970-01-01
相关资源
最近更新 更多