#python #python-3.x #pandas #list #dictionary
#python #python-3.x #pandas #Список #словарь
Вопрос:
У меня есть этот df :
df=pd.DataFrame({'stop_i':['stop_0','stop_0','stop_0','stop_1','stop_1','stop_0','stop_0'],'time':[0,10,15,50,60,195,205]})
Каждая строка соответствует time
(в секундах), в котором находилась шина stop_i
.
Во-первых, я хочу подсчитать, сколько раз шина была на stop_i
с 180 seconds
между последним просмотренным и следующим, который был замечен впервые. Результат был бы таким, {'stop_0' : 2,'stop_1': 1}
потому что в stop_0
последний раз, когда он был замечен в первый раз, был в 15s
затем он снова появляется в 195s
, поэтому 195-15<=180
тогда он считается равным 2 и stop_1
появляется только один раз
Во-вторых, я хочу получить этот dict : {'stop_0' : [[0,15],[195,205], 'stop_1': [[50,60]]}
содержащий минимальное и максимальное значения времени, когда шина была на stop_i
Есть ли способ сделать это с pandas, чтобы избежать цикла через df?
Спасибо!
Ответ №1:
Нет цикла
- сгенерируйте новый столбец, который представляет собой набор раз, когда шина останавливается (предполагается, что индекс является последовательным)
- из этого получаем первый и последний раз. затем создайте список первого / последнего раз. Плюс вычисления для > 180. Эта логика кажется странной. stop_1 имеет только одно посещение, поэтому количество 1 для> 180 является принудительным
- наконец, получите нужные вам словари.
df=pd.DataFrame({'stop_i':['stop_0','stop_0','stop_0','stop_1','stop_1','stop_0','stop_0'],'time':[0,10,15,50,60,195,205]})
dfp =(df
# group when a bus is at a stop
.assign(
grp=lambda dfa: np.where(dfa["stop_i"].shift()!=dfa["stop_i"], dfa.index, np.nan)
)
.assign(
grp=lambda dfa: dfa["grp"].fillna(method="ffill")
)
# within group get fisrt and last time it's at stop
.groupby(["stop_i","grp"]).agg({"time":["first","last"]})
.reset_index()
# based on expected output... in reality there is only 1 time bus is between stops
# > 180 seconds. stop_1 only has one visit to cannot be > 180s
.assign(
combi=lambda dfa: dfa.apply(lambda r: [r[("time","first")], r[("time","last")]] , axis=1),
stopchng=lambda dfa: dfa[("stop_i")]!=dfa[("stop_i")].shift(),
timediff=lambda dfa: dfa[("time","first")] - dfa[("time","last")].shift(),
)
)
# first requirement... which seems wrong
d1 = (dfp.loc[(dfp[("timediff")]>=180) | dfp[("stopchng")], ]
.groupby("stop_i")["stop_i"].count()
.to_frame().T.reset_index(drop="True")
.to_dict(orient="records")
)
# second requirement
d2 = (dfp.groupby("stop_i")["combi"].agg(lambda s: list(s))
.to_frame().T.reset_index(drop=True)
.to_dict(orient="records")
)
print(d1, d2)
вывод
[{'stop_0': 2, 'stop_1': 1}] [{'stop_0': [[0, 15], [195, 205]], 'stop_1': [[50, 60]]}]