【问题标题】:After groupby, evaluate value in column against column values in all rows in the group在 groupby 之后,根据组中所有行中的列值评估列中的值
【发布时间】:2020-04-15 12:35:20
【问题描述】:

我在 python 中寻找以下功能:

我有一个包含 4 列的 Pandas DataFrame:ID、StartDate、EndDate、Moment。

我想按 ID 进行分组,并评估组中的每一行是否 Moment 变量位于 StartDate 和 EndDate 之间的间隔之间。问题是我想为组中的每一行评估这个。例如,在下面的 DataFrame 中有两个组(ID=1 和 ID=2),两个组都包含 5 行。对于每一行,我想要两个组中每一行的布尔值,该行中的时刻变量是否落在组中的任何时间窗口中,窗口为 [date1,date2]。

import pandas as pd

i = pd.date_range('2018-04-11', periods=10, freq='2D20min')
i2 = pd.date_range('2018-04-12', periods=10, freq='2D20min')
i3 = pd.date_range('2018-04-9', periods=10, freq='1D6H')
id = ['1', '1', '1', '1', '1', '2', '2', '2', '2', '2']
ts = pd.DataFrame({'date1': i, 'date2': i2, 'moment': i3}, index=id)

ID  date1               date2               moment
1   2018-04-11 00:00:00 2018-04-12 00:00:00 2018-04-09 00:00:00
1   2018-04-13 00:20:00 2018-04-14 00:20:00 2018-04-10 06:00:00
1   2018-04-15 00:40:00 2018-04-16 00:40:00 2018-04-11 12:00:00
1   2018-04-17 01:00:00 2018-04-18 01:00:00 2018-04-12 18:00:00
1   2018-04-19 01:20:00 2018-04-20 01:20:00 2018-04-14 00:00:00
2   2018-04-21 01:40:00 2018-04-22 01:40:00 2018-04-15 06:00:00
2   2018-04-23 02:00:00 2018-04-24 02:00:00 2018-04-16 12:00:00
2   2018-04-25 02:20:00 2018-04-26 02:20:00 2018-04-17 18:00:00
2   2018-04-27 02:40:00 2018-04-28 02:40:00 2018-04-19 00:00:00
2   2018-04-29 03:00:00 2018-04-30 03:00:00 2018-04-20 06:00:00

在这种情况下,第一组第一行的时刻值不落在五个时间间隔中的任何一个。第二个也不行。第三个值 2018-04-11 12:00:00 确实落在第一行的区间内,因此我希望返回 True

想要的结果如下所示:

ID  date1               date2               moment              result
1   2018-04-11 00:00:00 2018-04-12 00:00:00 2018-04-09 00:00:00 False
1   2018-04-13 00:20:00 2018-04-14 00:20:00 2018-04-10 06:00:00 False
1   2018-04-15 00:40:00 2018-04-16 00:40:00 2018-04-11 12:00:00 True
1   2018-04-17 01:00:00 2018-04-18 01:00:00 2018-04-12 18:00:00 False
1   2018-04-19 01:20:00 2018-04-20 01:20:00 2018-04-14 00:00:00 True
2   2018-04-21 01:40:00 2018-04-22 01:40:00 2018-04-15 06:00:00 False
2   2018-04-23 02:00:00 2018-04-24 02:00:00 2018-04-16 12:00:00 False
2   2018-04-25 02:20:00 2018-04-26 02:20:00 2018-04-17 18:00:00 False
2   2018-04-27 02:40:00 2018-04-28 02:40:00 2018-04-19 00:00:00 False
2   2018-04-29 03:00:00 2018-04-30 03:00:00 2018-04-20 06:00:00 False

编辑

我已经用以下方法“解决”了这个问题,但我正在寻找一种更 Python 并且可能更快的方法......

boolean_result = []
for c in ts.index.unique():
    temp = ts.loc[ts.index == c]
    for row in temp.index:
        current_date = temp['moment'][row]
        boolean_result.append(max((temp['date1'] <= current_date)
                                  & (current_date <= temp['date2'])))
ts['Result'] = boolean_result

【问题讨论】:

    标签: python pandas date pandas-groupby


    【解决方案1】:

    如果您的数据框太大,这实际上可能会非常慢,并且可能存在除此之外的最佳解决方案:

    def time_in_range(start, end, x):
        """Return true if x is in the range [start, end]"""
        if start <= x and x <= end:
            return True
        else:
            return False
    
    # empty list to be appended
    result = []
    test_list = []
    
    for i in ts.index.unique():
    
        temp_df = ts[ts.index == i]
    
        for j in range(0, len(temp_df)):
            for k in range(0, len(temp_df)):    
                test_list.append(time_in_range(temp_df.date1.iloc[k], temp_df.date2.iloc[k], temp_df.moment.iloc[j]))
    
            result.append(any(test_list))
            # reset the list
            test_list = []
    
    ts['result'] = result
    

    【讨论】:

    • 感谢您的回复!我已经有了一个具有相同想法的“工作”解决方案,如下所示:python boolean_result = [] for c in ts.index.unique(): temp = ts.loc[ts.index == c] for row in temp.index: current_date = temp['moment'][row] boolean_result.append(max((temp['date1'] &lt;= current_date) &amp; (current_date &lt;= temp['date2']))) ts['Result'] = boolean_result 但我希望有一个更快、更 Python 的方法!
    猜你喜欢
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 2019-04-04
    • 1970-01-01
    • 2022-07-14
    • 2020-02-11
    • 1970-01-01
    相关资源
    最近更新 更多