Как в Python сравнивать значение с каждым последующим значением в строке, пока не будет выполнено условие

У меня есть таблица в общей структуре ниже:

пример кода:

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)

желаемый результат:

Можем ли мы рассматривать как идентификатор, так и дату в качестве фактора? Например, расчет даты должен выполняться для участника 117, и такой же расчет даты должен выполняться, если у нас есть несколько участников, например, элемент 118, 119 и т. д.

code_learner 02.06.2024 03:13
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
1
91
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Код

возможно, нужен цикл

# 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-ким. Можно ли выполнить расчет для каждого идентификатора, как показано на обновленном примере снимка экрана?

code_learner 01.06.2024 16:43

@Abhinav Я ответил на вопрос по твоему запросу и не думаю, что менять вопрос - это хорошее поведение. Ответы на stackoverflow предназначены для всех, а не только для спрашивающего, и вы сделали мой ответ бесполезным.

Panda Kim 01.06.2024 18:17

извините, я думал, что если кто-нибудь ответит на вопрос, он будет учитывать как идентификатор, так и дату в качестве факторов. Я отменил изменение.

code_learner 02.06.2024 02:56

@Abhinav Создайте новый вопрос, разделенный на группы. Я решу это за тебя.

Panda Kim 02.06.2024 02:58

спасибо, но, к сожалению, похоже, мне запретили задавать новые вопросы.

code_learner 02.06.2024 03:01

@Abhinav Если да, создайте часть «обновления» в основном сообщении и добавьте новый вопрос.

Panda Kim 02.06.2024 03:02

Давайте продолжим обсуждение в чате.

code_learner 02.06.2024 03:13

@Abhinav, я обновляю ваш вопрос и обновляю свой ответ для решения вашего дополнительного вопроса.

Panda Kim 02.06.2024 03:42

Другие вопросы по теме