У меня есть фрейм данных python, который выглядит так, он содержит много столбцов даты с разреженными заполненными значениями, не обязательно отсортированными слева направо. Невозможно избавиться от столбцов NaN, поскольку они могут содержать разреженное значение для некоторых идентификаторов.
Чего я пытаюсь добиться, так это найти окно даты производства, между двумя датами. Возьмем, к примеру, для ID aa дату производства 18.06.2022, она попадает между окном даты 13 15.06.2022 и датой 17 29.08.2022, и я хочу пометить ее в корзине даты 13. А для ID bb дата производства находится между датой 6 и датой 7, и я хочу отметить ее в ведре даты 6. Примеры выходных данных приведены в последнем столбце.
Каков наилучший способ добиться желаемого результата в python? Спасибо!
я имею в виду, что я хочу пометить его как date13, чтобы определить фазу даты производства.






По сути, вам нужно получить имя столбца ближайшей даты производства? Если это так, вы можете использовать:
df["output"] = df.iloc[:, 1:].apply(
lambda x: (pd.to_datetime(x) -pd.to_datetime(x)["production date"])
.abs().drop("production date").idxmin(), axis=1)
Выход :
print(df)
ID production date date1 date2 ... date17 date 18 date 19 output
0 aa 6/18/2022 4/20/2022 NaN ... 8/29/2022 NaN 10/10/2022 date13
1 bb 11/25/2021 5/25/2021 NaN ... 8/29/2021 NaN 10/15/2021 date6
2 CC 6/20/2022 4/25/2022 NaN ... 8/29/2022 NaN 10/10/2022 date1
3 dd 7/30/2020 3/25/2020 NaN ... 7/29/2020 NaN 9/10/2020 date17
Обновлять :
окно я имею в виду наименьшее окно, в которое он попадает, т.е. дата 18.06.2022, наименьшее окно, в которое она попадает, находится между дата13 15.06.2022 по дата17 19.08.2022. И я хочу пометить его имя столбца той даты начала окна, которая равна date13.
def smallest_window(ser):
diff = (pd.to_datetime(ser) - pd.to_datetime(ser)["production date"]).dt.days
left_date = diff.loc[lambda x: x.lt(0)].idxmax() #.le(0) to make it inclusive
right_date = diff.loc[lambda x: x.gt(0)].idxmin() #.ge(0) to make it inclusive
return [left_date, right_date]
df["date_intervals"] = df.iloc[:, 1:].apply(smallest_window, axis=1)
df["date_col_names"] = df["date_intervals"].str[0] # use `.str[1]` to get the last date
Выход :
print(df)
ID production date date1 ... date 19 date_intervals date_col_names
0 aa 8/18/2022 4/20/2022 ... 10/10/2022 [date13, date17] date13
1 bb 11/25/2021 5/25/2021 ... 10/15/2021 [date6, date7] date6
2 CC 6/20/2022 4/25/2022 ... 10/10/2022 [date1, date17] date1
3 dd 7/30/2020 3/25/2020 ... 9/10/2020 [date17, date 19] date17
Привет спасибо за ваш ответ! Одно уточнение: я не ищу ближайшую дату, я ищу дату производства окна и помечаю ее в столбце даты начала этого окна. т. е. если дата производства ID aa равна 10.06.2022, она попадает в окно даты 1 20.04.2022 и даты 13 15.06.2022, и я хочу отметить начало даты производства окна, в которое попадает, что date1 в этом случае. Надеюсь, это поможет объяснить. Спасибо!
Извините, но логика мне все еще не ясна. В примере, которым вы поделились в своем вопросе, для идентификатора aa существует так много возможностей. Как вы решаете/выбираете интервал? production date 18 июня 2022 г. выпадает 1) с 20 апреля 2022 г. по 14 ноября 2023 г., 2) с 15 июня 2022 г. по 10 октября 2022 г. и многие другие..
О, я понимаю вашу точку зрения, окно, я имею в виду наименьшее окно, в которое он попадает, то есть дата производства — 18.06.2022, наименьшее окно, в которое он попадает, — между датой 13 15.06.2022 и датой 17 19.08.2022. И я хочу пометить его именем столбца этой начальной даты окна, то есть date13.
Тогда мой подход должен сработать для вас. Можете ли вы объяснить, почему это не так?
Конечно, если мы изменим дату производства id aa на 18.08.2022, ваш подход пометит эту дату записи17 как 19.08.2022 как ближайшую к этой дате, но желаемый результат состоит в том, чтобы пометить ее как начало этой даты. наименьшее окно, которое должно быть date13 (наименьшее окно - date13 15.06.2022 до date17 19.08.2022).
Достаточно справедливо;) Я обновил свой ответ, можете ли вы его проверить?
Большой! Это сработало! Я добавил два столбца: один для сегодняшней даты, другой для 01.01.1900, чтобы обрабатывать некоторые случаи, когда есть только одно значение даты, отличное от даты производства, и это полностью работает! Большое спасибо :)
что вы подразумеваете под «я хочу отметить это в ведре даты 13»?