通过迭代比较另一列的上一个元素来扩大分组的熊猫数据框

时间:2020-03-11 08:24:49

标签: pandas dataframe apply

我的问题与我问过here的另一个问题有关,但由于涉及两列而有所不同。

我有一个熊猫数据框,其中有多个组(车辆)在特定日期的出发和到达时间。这些时间存储为字符串,例如'2330'对应于11.30pm,'30'对应于0.30am。这些时间按时间顺序排列,但有时可能会越过午夜线。我想在新栏中以1表示这些时刻。更具体地说,我认为我需要检查(1)每个出发时间是否比先前记录的到达时间“早”(这意味着出发时间必须是新的一天)和(2)每个到达时间是否早于当前记录的出发时间(这意味着到达必须在新的一天)。

示例:

df = pd.DataFrame.{'group' : ["A","A","A","B","B","B"],
                   'departure' : [2030, 2300, 200, 1930, 200, 300],
                   'arrival' : [2130, 30, 230, 100, 230, 400]})

收益

  group  departure  arrival
0     A       2030     2130
1     A       2300       30
2     A        200      230
3     B       1930      100
4     B        200      230
5     B        300      400

所需的输出:

  group  departure  arrival  dep_new  arr_new
0     A       2030     2130  0        0
1     A       2300       30  0        1
2     A        200      230  1        1
3     B       1930      100  0        1
4     B        200      230  1        1
5     B        300      400  1        1

将我的previous question的答案应用到当前的到达位置与先前的到达位置以及当前的离开位置与之前的到达位置进行比较,可能无法正常工作,因为有些极端情况无法使用这种方法。

希望您能提供帮助!

2 个答案:

答案 0 :(得分:0)

您可以尝试:

df = pd.DataFrame({'group' : ["A","A","A","B","B","B"],
                   'departure' : [2030, 2300, 200, 1930, 200, 300],
                   'arrival' : [2130, 30, 230, 100, 230, 400]})
dep_new = list()
arr_new = list()

for grp in df.groupby('group'):
    dep_new.append((grp[1].arrival < grp[1].departure).astype(int))
    arr_new.append((grp[1].departure > grp[1].arrival.shift(1)).astype(int))

arr_new_flat = list()
for sublist in arr_new:
    for item in sublist:
        arr_new_flat.append(item)

dep_new_flat = list()
for sublist in dep_new:
    for item in sublist:
        dep_new_flat.append(item)

df['dep_new'] = dep_new_flat
df['arr_new'] = arr_new_flat

print(df)

结果:

  group  departure  arrival  dep_new  arr_new
0     A       2030     2130        0        0
1     A       2300       30        1        1
2     A        200      230        0        1
3     B       1930      100        1        0
4     B        200      230        0        1
5     B        300      400        0        1

答案 1 :(得分:0)

在@Rene的帮助下,我想找到了解决方法。

def _activity_nextday(df):
    deppivot = (df.departure < df.arrival.shift(1)).astype(int) # if departure is "before" arrival on previous day, then this means that departure is on new day
    arrpivot = (df.arrival < df.departure).astype(int)  # if arrival is "before" departure, then this means that arrival is on new day

    agglist = [None] * (len(arrpivot) + len(deppivot))
    agglist[::2] = deppivot
    agglist[1::2] = arrpivot
    cumlist = list(np.array(agglist).cumsum())
    d_cum = cumlist[::2]
    a_cum = cumlist[1::2]

    return pd.DataFrame({"dep_new" : d_cum, "arr_new": a_cum})

df[["dep_new", "arr_new"]] = df.groupby("group").apply(lambda x: _activity_nextday(x)).reset_index(level="group").reset_index(drop=False)[["dep_new", "arr_new"]]

结果:

  group  departure  arrival  dep_new  arr_new
0     A       2030     2130        0        0
1     A       2300     2330        0        0
2     A        200      230        1        1
3     B       1930      100        0        1
4     B        200      230        1        1
5     B        300      400        1        1