【问题标题】:"Iterative" Window function on subset of dataframe数据帧子集上的“迭代”窗口函数
【发布时间】:2018-10-24 16:01:40
【问题描述】:

我正在寻找一种从下面的数据框df 创建列'min_value' 的方法。对于每一行 i,我们从整个数据框中子集对应于第 i 行的分组 ['Date_A', 'Date_B'] 并且条件 'Advance' 小于第 i 行的 'Advance' 的所有记录,最后我们选择最小值此子集中的列'Amount' 为第i 行设置'min_value'

初始数据框:

dates_A = ['2017-12-25','2017-12-25','2017-12-25','2018-1-25','2018-1-25','2018-1-25']
Date_A = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_A]
dates_B = ['2018-1-1','2018-1-1','2018-1-1','2018-2-1','2018-2-1','2018-2-1']
Date_B = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_B]
df = pd.DataFrame({'Date_A':Date_A,
       'Date_B':Date_B,        
       'Advance' : [10,103,200,5,8,150],
       'Amount' : [180,220,200,230,220,240]})

df  = df [['Date_A', 'Date_B', 'Advance', 'Amount']]
df 

期望的输出:

dates_A = ['2017-12-25','2017-12-25','2017-12-25','2018-1-25','2018-1-25','2018-1-25']
Date_A = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_A]
dates_B = ['2018-1-1','2018-1-1','2018-1-1','2018-2-1','2018-2-1','2018-2-1']
Date_B = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_B]
df_out = pd.DataFrame({'Date_A':Date_A,
       'Date_B':Date_B,        
       'Advance' : [10,103,200,5,8,150],
       'Amount' : [180,220,200,230,220,240],
       'min_value': [180,180,180,230,230,220] })

df_out  = df_out [['Date_A', 'Date_B', 'Advance', 'Amount','min_value']]
df_out 

我编写了以下循环,我认为它可以完成这项工作,但运行时间太长,我想必须有更有效的方法来完成这项工作。

for i in range(len(df)):
    date1=df['Date_A'][i] #select the date A of the row i 
    date2=df['Date_B'][i] #select the date B of the row i 
    advance= df['Advance'][i] #select the advance of the row i 
    df.loc[i,'min_value'] = df[df['Date_A']==date1][df['Date_B']==date2][df['Advance']<advance]['Amount'].min()  # subset the entire dataframe to meet dates and advance conditions
    df.loc[df['min_value'].isnull(),'min_value']=df['Amount'] # for the smallest advance value, ste min=to its own amount
df

我希望它足够清楚,感谢您的帮助。

改进问题 非常感谢您的回答。对于最后一部分,NA 行,我想用 Date_A,Date_B,advance 分组的总量替换行的数量,这样我就有了 date_A 之前最后一天的总体最小值

提高期望的输出(最小提前值的两个记录器)

dates_A = ['2017-12-25','2017-12-25','2017-12-25','2017-12-25']
Date_A = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_A]
dates_B = ['2018-1-1','2018-1-1','2018-1-1','2018-1-1']
Date_B = [pd.to_datetime(date, format='%Y-%m-%d').date() for date in dates_B]

df_out = pd.DataFrame({'Date_A':Date_A,
       'Date_B':Date_B,        
       'Advance' : [5,8,150,5],
       'Amount' : [230,220,240,225],
       'min_value': [225,230,220,225] })

df_out  = df_out [['Date_A', 'Date_B', 'Advance', 'Amount','min_value']]
df_out 

谢谢

【问题讨论】:

  • 您也应该在帖子中包含所需的输出。我不清楚您的Advance 条件到底是什么?

标签: python pandas function window subset


【解决方案1】:

您可以在'Advance'apply 函数cumminshift 对列'Amount' 进行排序后,在'Date_A''Date_B' 上使用groupby。然后将fillna'Amount' 列中的值一起使用,例如:

df['min_value'] = (df.sort_values('Advance').groupby(['Date_A','Date_B'])['Amount']
                      .apply(lambda ser_g: ser_g.cummin().shift()).fillna(df['Amount']))

你会得到:

       Date_A      Date_B  Advance  Amount  min_value 
0  2017-12-25  2018-01-01       10     180      180.0      
1  2017-12-25  2018-01-01      103     220      180.0 
2  2017-12-25  2018-01-01      200     200      180.0 
3  2018-01-25  2018-02-01        5     230      230.0 
4  2018-01-25  2018-02-01        8     220      230.0 
5  2018-01-25  2018-02-01      150     240      220.0 

【讨论】:

  • 这是最好的解决方案。 +1
  • 结果很好,我只是在主要问题上添加了一个问题来稍微改进一下
  • @mo29 应该作为一个单独的问题发布,因为它需要不同的解决方案
猜你喜欢
  • 2016-10-27
  • 1970-01-01
  • 2018-11-21
  • 2022-01-17
  • 1970-01-01
  • 2019-04-23
  • 2013-10-25
  • 2018-03-12
  • 2018-03-27
相关资源
最近更新 更多