У меня есть набор данных для каждого случая. Я пытаюсь заполнить последнее unassigned
из каждого случая дату case_closed
.
case_nb attorney cas_closed_date assigned last_event
1 A 2015-07-02 2015-07-02 2015-07-02
2 B 2015-09-10 2015-09-10 2015-09-10
3 C 2016-03-24 2016-03-24 2016-03-24
4 D 2018-06-07 2013-10-21 2014-02-06
4 C 2018-06-07 2013-09-13 2013-09-13
4 F 2018-06-07 2018-03-31 2018-04-05
(Для тиражирования:
df = pd.DataFrame({'assigned': {0: pd.Timestamp('2015-07-02'), 1: '2015-09-10', 2: '2016-03-24', 3: '2013-10-21', 4: '2013-09-13', 5: '2018-03-31'},
'attorney': {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'C', 5: 'F'},
'cas_closed_date': {0: pd.Timestamp('2015-07-02'), 1: '2015-09-10', 2: '2016-03-24', 3: '2018-06-07', 4: '2018-06-07', 5: '2018-06-07'},
'case_nb': {0: 1, 1: 2, 2: 3, 3: 4, 4: 4, 5: 4},
'last_event': {0: pd.Timestamp('2015-07-02'), 1: '2015-09-10', 2: '2016-03-24', 3: '2014-02-06', 4: '2013-09-13', 5: '2018-04-05'}}
)
В моем наборе данных содержится номер дела, назначенный адвокат, дата закрытия дела, дата назначения адвоката и последнее событие, на котором появился адвокат. В приведенном выше примере я бы хотел, чтобы последняя строка была
4 F 2018-06-07 2018-03-31 2018-06-07
Я видел несколько способов заполнения НС на основе данных в одном столбце, таких как этот вопрос. Но эти способы используют transform
, которое я не могу использовать для использования нескольких столбцов.
То, к чему я до сих пор работаю, apply
, но не transform
:
def fixdate(gp):
last_unasgn = gp.iloc[-1]['last_event']
if gp.iloc[-1]['cas_closed_date'] > last_unasgn:
return gp.iloc[-1]['cas_closed_date']
else:
return last_unasgn
asmt.groupby('evt_file_number').apply(lambda x: fixdate(x))
> 4 2018-06-07
Есть ли способ использовать transform
? Если нет, то какой лучший способ использовать эти агрегированные данные для заполнения моего исходного набора данных?
В случае, когда тот же case_nb
никогда не назначается в тот же день двум различным адвокатам, вы можете попробовать это решение.
import numpy as np
import pandas as pd
df = pd.DataFrame({'assigned': {0: pd.Timestamp('2015-07-02'), 1: '2015-09-10',
2: '2016-03-24', 3: '2013-10-21', 4: '2013-09-13',
5: '2018-03-31'},
'attorney': {0: 'A', 1: 'B', 2: 'C', 3: 'D', 4: 'C', 5: 'F'},
'cas_closed_date': {0: pd.Timestamp('2015-07-02'), 1: '2015-09-10',
2: '2016-03-24', 3: '2018-06-07', 4: '2018-06-07',
5: '2018-06-07'},
'case_nb': {0: 1, 1: 2, 2: 3, 3: 4, 4: 4, 5: 4},
'last_event': {0: pd.Timestamp('2015-07-02'), 1: '2015-09-10',
2: '2016-03-24', 3: '2014-02-06', 4: '2013-09-13',
5: '2018-04-05'}})
out = df.groupby("case_nb")["assigned"].max().reset_index()
out["last"] = True
df = pd.merge(df, out, how="left", on= ["case_nb", "assigned"])
df["last_event"] = np.where(df["last"] == True, df["cas_closed_date"], df["last_event"])
del df["last"], out
Возможно есть более элегантное решение, но по крайней мере это векторное (см np.where
) и не использовать apply
. pandas performaces.
EDIT В случае, если вы хотите использовать transform
есть этот вариант, который кажется мне самым быстрым решением.
df["last_assigned"] = df.groupby("case_nb")["assigned"].transform("max")
df["last_event"] = np.where(df["assigned"]==df["last_assigned"],
df["cas_closed_date"],
df["last_event"])
del df["last_assigned"]
Операция .transform
передает все столбцы для каждой группы в качестве одномерной серии для функции, а операция .apply
передает все столбцы для каждой группы в качестве DataFrame для функции. Таким образом, .transform
работает на одной серии (или столбце) за раз, а .apply
работает для всего DataFrame (или всех столбцов). Надеюсь это поможет.
В итоге я сделал комбинацию transform
и просто индексирования.
df = df.sort_values(['case_nb', 'last_event'])
df['last_unassigned'] = df.groupby('case_nb')['last_event'].transform('last')
df.loc[(df['last_event'] == df['last_unassigned'])
& (df['last_unassigned'] != df['cas_closed_date']), 'last_event'] = df['cas_closed_date']
df['last_unassigned'] != df['cas_closed_date']
является избыточным. Я имею в виду, что если эти значения совпадают, это не повредит обновлению df["last_event"]
с самим собой.
%%timeit%%, your
решение np.where` заняло1.45 ms ± 37.3 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
, а мое решениеloc
заняло2.14 ms ± 72.2 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
. Так что я бы сказал, чтоnp.where
- явный победитель.df
?