Pandas Dataframe - для каждой строки возвращать количество других строк с перекрывающимися датами - PullRequest
3 голосов
/ 08 октября 2019

У меня есть датафрейм с проектами, датами начала и окончания. Для каждой строки я хотел бы вернуть количество других проектов в процессе, когда проект начался. Как вы вкладываете циклы при использовании df.apply()? Я попытался использовать цикл for, но мой фрейм данных большой и занимает слишком много времени.

import datetime as dt

data = {'project' :['A', 'B', 'C'],
        'pr_start_date':[dt.datetime(2018, 9, 1), dt.datetime(2019, 4, 1), dt.datetime(2019, 6, 8)],
        'pr_end_date': [dt.datetime(2019, 6, 15), dt.datetime(2019, 12, 1), dt.datetime(2019, 8, 1)]}

df = pd.DataFrame(data)

def cons_overlap(start):
    overlaps = 0
    for i in df.index:
        other_start = df.loc[i, 'pr_start_date']
        other_end = df.loc[i, 'pr_end_date']
        if (start > other_start) & (start < other_end):
            overlaps += 1

    return overlaps

df['overlap'] = df.apply(lambda row: cons_overlap(row['pr_start_date']), axis=1)

Это вывод, который я ищу:

    pr  pr_start_date pr_end_date   overlap
0   A   2018-09-01    2019-06-15    0
1   B   2019-04-01    2019-12-01    1
2   C   2019-06-08    2019-08-01    2

Ответы [ 3 ]

3 голосов
/ 08 октября 2019

Я предлагаю вам воспользоваться NumPy Broadcast :

ends = df.pr_start_date.values < df.pr_end_date.values[:, None]
starts = df.pr_start_date.values > df.pr_start_date.values[:, None]
df['overlap'] = (ends & starts).sum(0)
print(df)

Выход

  project pr_start_date pr_end_date  overlap
0       A    2018-09-01  2019-06-15        0
1       B    2019-04-01  2019-12-01        1
2       C    2019-06-08  2019-08-01        2

Оба конца и начала являются матрицами3x3, которые являются истинными при выполнении условия:

# ends   
[[ True  True  True]  
 [ True  True  True]
 [ True  True  True]]

# starts
[[False  True  True]
 [False False  True]
 [False False False]]

Затем найдите пересечение с логическим & и суммой по столбцам (sum(0)).

2 голосов
/ 08 октября 2019

должно быть быстрее, чем ваш цикл for

enter image description here

0 голосов
/ 09 октября 2019

Я предполагаю, что строки отсортированы по дате начала, и проверяю ранее запущенные проекты, которые еще не завершены. Df.index.get_loc (r.name) возвращает индекс обрабатываемой строки.

df["overlap"]=df.apply(lambda r: df.loc[:df.index.get_loc(r.name),"pr_end_date"].gt(r["pr_start_date"]).sum()-1, axis=1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...