首页 > 解决方案 > 如何根据条件从不同的列中创建一个组?

问题描述

我有一个看起来像这样的数据框:

    Air-line        City        Time        ID

0   easyJet         London      20:40       1
1   airberlin       Berlin      10:30       2
2   Emarite         Dubai       21:45       3
3   Qatar Airways   Newyork     10:30       4
4   easyJet         London      20:46       5
5   airberlin       Berlin      10:34       6
.
.
.
.
99   Qatar Airways   London      20:40     13
100   airberlin    Berlin        10:32     20

我想要做的是使用 groupby 并根据列 ID 从列“Air-lines”、“City”和“Time”中创建一个组,以更改列 ID 中的值。因此,Air-line、City 和 Time 中具有相同值的行应该具有相同的 ID。为此,我有以下代码:

df['ID'] = df.groupby(['Air-line','City','Time'])['ID'].transform('first') 

但问题是我想更改代码,以便不仅包括“时间”列中的确切值,还应该包括 +6 或 -6 分钟之间的差值。

我期望的是:

    Air-line        City        Time        ID

0   easyJet         London      20:40       1
1   airberlin       Berlin      10:30       2
2   Emarite         Dubai       21:45       3
3   Qatar Airways   Newyork     10:30       4
4   easyJet         London      20:46       1
5   airberlin       Berlin      10:34       2
.
.
.
.
99   Qatar Airways   London      20:40       13
100   airberlin    Berlin         10:32       2

你能告诉我如何添加这个条件吗?任何帮助将不胜感激。非常感谢

标签: pythonpandasconditional-statementspandas-groupby

解决方案


您可以time使用 6 分钟的步骤对列进行分类,如下所示。我在这里使用pandas.cut功能。当bins我传递从pd.date_range. 在pd.cut我使用right=False包含区间左侧的点并排除区间右侧的点。

我以一个小的数据框为例,但你会明白的。

import datetime

import pandas as pd


df = pd.DataFrame({
    'time': ['20:30', '20:33', '20:36', '20:40', '20:42'],
    'ID': [1, 2, 3, 4, 5],
})
df['time'] = pd.to_datetime(df['time'])

start = df['time'].min()
end = df['time'].max() + pd.Timedelta('6min')
bins = pd.date_range(start, end, freq='6T')

cut = pd.cut(df['time'], bins=bins, right=False)
df['time_category'] = cut

df['ID'] = df.groupby('time_category')['ID'].transform('first')

print(df)

输出

                 time  ID                               time_category
0 2021-02-03 20:30:00   1  [2021-02-03 20:30:00, 2021-02-03 20:36:00)
1 2021-02-03 20:33:00   1  [2021-02-03 20:30:00, 2021-02-03 20:36:00)
2 2021-02-03 20:36:00   3  [2021-02-03 20:36:00, 2021-02-03 20:42:00)
3 2021-02-03 20:40:00   3  [2021-02-03 20:36:00, 2021-02-03 20:42:00)
4 2021-02-03 20:42:00   5  [2021-02-03 20:42:00, 2021-02-03 20:48:00)

无日期分箱

还有另一种方法。您提到您需要避免在分组中使用日期。不幸的是,我没有设法使用 pandas internals 扩展解决方案。但这可以通过另一种方式实现。

让我们bins从 00:00 到 23:54 手动创建并为每个人分配密钥。然后我们将使用一个categorize函数将相应的键分配给时间值。请注意,我在这里创建new_time了使用time.strptime转换的列。就是这个专栏,然后我对其进行分类。

import itertools
from functools import partial
import time

import pandas as pd

bins = [
    time.strptime(f'{hour}:{minute}', '%H:%M')
    for hour, minute in itertools.product(range(24), range(0, 60, 6))
]

bins_mapping = {
    index: value
    for index, value in enumerate(sorted(bins))
}


def categorize(t, bins_mapping):
    for index, value in bins_mapping.items():
        if value > t:
            break
    return index


df = pd.DataFrame({
    'time': ['20:30', '20:33', '20:36', '20:40', '20:42'],
    'ID': [1, 2, 3, 4, 5],
})

df['new_time'] = df['time'].apply(lambda x: time.strptime(x, '%H:%M'))
df['time_category'] = df['new_time'].apply(
    partial(categorize, bins_mapping=bins_mapping)
)
df['ID'] = df.groupby('time_category')['ID'].transform('first')

print(df)

输出

    time  ID                           new_time  time_category
0  20:30   1  (1900, 1, 1, 20, 30, 0, 0, 1, -1)            206
1  20:33   1  (1900, 1, 1, 20, 33, 0, 0, 1, -1)            206
2  20:36   3  (1900, 1, 1, 20, 36, 0, 0, 1, -1)            207
3  20:40   3  (1900, 1, 1, 20, 40, 0, 0, 1, -1)            207
4  20:42   5  (1900, 1, 1, 20, 42, 0, 0, 1, -1)            208

推荐阅读