У меня есть таблица в общей структуре ниже:
пример кода:
import pandas as pd
data = {
'ID': [117, 117, 117, 117, 117, 117],
'Date': ['2023-11-14', '2024-01-25', '2024-02-01', '2024-02-04', '2024-02-11', '2024-03-04']
}
df = pd.DataFrame(data)
Я хотел бы сравнить первую строку со следующей, пока разница между датами не достигнет некоторого порога, скажем, 30 дней. Затем, как только эта строка достигнет порогового значения, я хотел бы сравнить следующую строку с последующей строкой. Это будет выглядеть так:
Результат с использованием порога 30:
Итак, повторим: сравнивается ПЕРВАЯ строка с последующими строками до тех пор, пока не будет достигнут некоторый порог. Затем отсчет начинается заново с первого повторения после этого внутри группы до последующих рядов внутри группы.
Я пробовал это, но до сих пор мне не удалось получить правильное сравнение по строкам, чтобы даже реализовать бит порога.
thres = 30
i = 0
control = True
for record in df['Date']:
if record > thres:
print(i, 'in position!', i)
control = False
i += 1
Обновлять
Я хочу сделать вышеизложенное с группами на основе идентификатора.
пример кода:
import pandas as pd
data = {
"ID": [117, 117, 117, 117, 117, 117, 118, 118, 118, 118, 118, 118],
"Date": ["2023-11-14", "2024-01-25", "2024-02-01", "2024-02-04", "2024-02-11", "2024-03-04",
"2024-01-02", "2024-01-28", "2024-02-04", "2024-02-18", "2024-03-11", "2024-06-05"]
}
df = pd.DataFrame(data)
желаемый результат:






Код
возможно, нужен цикл
# example code
import pandas as pd
data = {'ID': [117, 117, 117, 117, 117, 117], 'Date': ['2023-11-14', '2024-01-25', '2024-02-01', '2024-02-04', '2024-02-11', '2024-03-04']}
df = pd.DataFrame(data)
# make variable dates (convert dtype to datetime)
dates = pd.to_datetime(df['Date'])
# chk 30 days (you can change your target by changing variable thresh)
thresh = 30
# date is compared as variable ref
ref = dates.iloc[0]
# variable result is list to hold the flags. First element is 1
result = [1]
# append flag(0 or 1) to result variable based on 30 days (loop)
for date in dates.iloc[1:]:
if (date - ref).days >= thresh:
result.append(1) # append 1 as a flag if over 30 days
ref = date # change refrence date
else:
result.append(0) # append 0 as a flag unless over 30 days
# make flag column using result variable
out = df.assign(flag=result)
вне
ID Date flag
0 117 2023-11-14 1
1 117 2024-01-25 1
2 117 2024-02-01 0
3 117 2024-02-04 0
4 117 2024-02-11 0
5 117 2024-03-04 1
проверка с новым образцом
df = (pd.DataFrame(pd.date_range('2024-01-01', '2024-04-01'), columns=['Date'])
.sample(10, random_state=3).sort_values('Date').reset_index(drop=True)
)
Если применить приведенный выше код к новому образцу (df), вы получите следующий результат
вне:
Date Date flag
0 2024-01-10 0 2024-01-10 1
1 2024-02-15 1 2024-02-15 1
2 2024-02-22 2 2024-02-22 0
3 2024-02-25 3 2024-02-25 0
4 2024-02-28 -> 4 2024-02-28 0
5 2024-03-09 5 2024-03-09 0
6 2024-03-11 6 2024-03-11 0
7 2024-03-25 7 2024-03-25 1
8 2024-03-26 8 2024-03-26 0
9 2024-03-31 9 2024-03-31 0
Ответ на обновленный вопрос
Замените приведенное выше пользовательской функцией и примените пользовательскую функцию с помощью groupby + apply.
# example code
import pandas as pd
data = {"ID": [117, 117, 117, 117, 117, 117, 118, 118, 118, 118, 118, 118], "Date": ["2023-11-14", "2024-01-25", "2024-02-01", "2024-02-04", "2024-02-11", "2024-03-04","2024-01-02", "2024-01-28", "2024-02-04", "2024-02-18", "2024-03-11", "2024-06-05"]}
df = pd.DataFrame(data)
# make custom function
def get_flag(d, thresh=30):
dates = pd.to_datetime(d['Date'])
ref = dates.iloc[0]
result = [1]
for date in dates.iloc[1:]:
if (date - ref).days >= thresh:
result.append(1)
ref = date
else:
result.append(0)
return d.assign(flag=result)
# groupby + apply + custom function
out = df.groupby('ID', group_keys=False).apply(get_flag)
вне:
ID Date flag
0 117 2023-11-14 1
1 117 2024-01-25 1
2 117 2024-02-01 0
3 117 2024-02-04 0
4 117 2024-02-11 0
5 117 2024-03-04 1
6 118 2024-01-02 1
7 118 2024-01-28 0
8 118 2024-02-04 1
9 118 2024-02-18 0
10 118 2024-03-11 1
11 118 2024-06-05 1
Спасибо! @panda-ким. Можно ли выполнить расчет для каждого идентификатора, как показано на обновленном примере снимка экрана?
@Abhinav Я ответил на вопрос по твоему запросу и не думаю, что менять вопрос - это хорошее поведение. Ответы на stackoverflow предназначены для всех, а не только для спрашивающего, и вы сделали мой ответ бесполезным.
извините, я думал, что если кто-нибудь ответит на вопрос, он будет учитывать как идентификатор, так и дату в качестве факторов. Я отменил изменение.
@Abhinav Создайте новый вопрос, разделенный на группы. Я решу это за тебя.
спасибо, но, к сожалению, похоже, мне запретили задавать новые вопросы.
@Abhinav Если да, создайте часть «обновления» в основном сообщении и добавьте новый вопрос.
Давайте продолжим обсуждение в чате.
@Abhinav, я обновляю ваш вопрос и обновляю свой ответ для решения вашего дополнительного вопроса.
Можем ли мы рассматривать как идентификатор, так и дату в качестве фактора? Например, расчет даты должен выполняться для участника 117, и такой же расчет даты должен выполняться, если у нас есть несколько участников, например, элемент 118, 119 и т. д.