Pandas — перекрестные ссылки с DatetimeIndex — Groupby

У меня есть данные многих компаний по месяцам (конец месяца). Я хочу создать новые столбцы с groupby для each company, где:

  • new_col с июля этого года по июнь следующего года будет принимать значение декабря прошлого года.
  • Например, значение new_col с июля 2000 г. по июнь 2001 г. будет равно значению old_col декабря 1999 г.

Вы можете скачать образцы данных здесь: https://www.dropbox.com/s/oz1ltblh6u0chzt/tem_20220506.csv?dl=0

Я пытался использовать эту строку кода, но безуспешно:

df = pd.read_csv('tem_20220506.csv', parse_dates=['date'])
df.drop(columns=['new_col', 'Note'], inplace=True)
df = df.set_index('date').rename_axis(None)

df['new_col'] = df.groupby('comp').apply(lambda g: --- ) # ← I am now stuck here

Выход желания:

           comp  old_col  new_col  \
2000-01-31    a        1      NaN   
2000-02-29    a        2      NaN   
2000-03-31    a        3      NaN   
2000-04-30    a        4      NaN   
2000-05-31    a        5      NaN   
2000-06-30    a        6      NaN   
2000-07-31    a        7      NaN   
2000-08-31    a        8      NaN   
2000-09-30    a        9      NaN   
2000-10-31    a       10      NaN   
2000-11-30    a       11      NaN   
2000-12-31    a       12      NaN   
2001-01-31    a       13      NaN   
2001-02-28    a       14      NaN   
2001-03-31    a       15      NaN   
2001-04-30    a       16      NaN   
2001-05-31    a       17      NaN   
2001-06-30    a       18      NaN   
2001-07-31    a       19   12.000   
2001-08-31    a       20   12.000   
2001-09-30    a       21   12.000   
2001-10-31    a       22   12.000   
2001-11-30    a       23   12.000   
2001-12-31    a       24   12.000   
2002-01-31    a       25   12.000   
2002-02-28    a       26   12.000   
2002-03-31    a       27   12.000   
2002-04-30    a       28   12.000   
2002-05-31    a       29   12.000   
2002-06-30    a       30   12.000   
2002-07-31    a       31   24.000   
2002-08-31    a       32   24.000   
2002-09-30    a       33   24.000   
2002-10-31    a       34   24.000   
2002-11-30    a       35   24.000   
2002-12-31    a       36   24.000   
2000-01-31    b      101      NaN   
2000-02-29    b      102      NaN   
2000-03-31    b      103      NaN   
2000-04-30    b      104      NaN   
2000-05-31    b      105      NaN   
2000-06-30    b      106      NaN   
2000-07-31    b      107      NaN   
2000-08-31    b      108      NaN   
2000-09-30    b      109      NaN   
2000-10-31    b      110      NaN   
2000-11-30    b      111      NaN   
2001-01-31    b      113      NaN   
2001-02-28    b      114      NaN   
2001-03-31    b      115      NaN   
2001-04-30    b      116      NaN   
2001-05-31    b      117      NaN   
2001-06-30    b      118      NaN   
2001-07-31    b      119      NaN   
2001-08-31    b      120      NaN   
2001-09-30    b      121      NaN   
2001-10-31    b      122      NaN   
2001-11-30    b      123      NaN   
2001-12-31    b      124      NaN   
2002-01-31    b      125      NaN   
2002-02-28    b      126      NaN   
2002-03-31    b      127      NaN   
2002-04-30    b      128      NaN   
2002-05-31    b      129      NaN   
2002-06-30    b      130      NaN   
2002-07-31    b      131  124.000   
2002-08-31    b      132  124.000   
2002-10-31    b      134  124.000   
2002-11-30    b      135  124.000   
2002-12-31    b      136  124.000   

(!!) Обратите внимание, что: для комп==b:

  • Это NaN с июля 2001 г. по июнь 2002 г., потому что значение декабря 2000 г. равно missing

  • Есть missing сен-2002, но это нормально

Почему в 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 может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
20
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
df = pd.read_csv('tem_20220506.csv', parse_dates=['date'])
df.drop(columns=['new_col', 'Note'], inplace=True)
df.set_index('date', inplace=True)

использование вспомогательной функции для получения нового столбца на основе старого столбца

def helper_func(x):
    # get the date values corresponding to month = 12
    req_values = x[x.index.month == 12].to_dict()['old_col']

    # iterate over those dates and replace July to June range depending on the year of the date
    for date_value, old_col_value in req_values.items():
        x.loc[f'{date_value.year+1}-07-31':f'{date_value.year+2}-06-30', 'new_col'] = old_col_value
        
    return x
df['new_col'] = df.groupby('comp')[['old_col']].apply(helper_func)['new_col']

Это предоставит фреймворк данных в качестве желаемого результата.

Альтернативная вспомогательная функция

def helper_fun2(x):
    """
    1. iterate over years
    2. update July to June next two years value, using DEC value of current year
    """
    for year in x.index.year.unique():
        if f'{year}-12-31' in x.index:
            x.loc[f'{year+1}-07-31':f'{year+2}-06-30', 'new_col'] = x.loc[f'{year}-12-31']['old_col']
        
    return x

Спасибо, можете мне немного объяснить. Когда я пытаюсь df[df.index.month==12].to_dict()['old_col'], почему в словаре только 3 строки значений. Разве не должно быть 5? Потому что когда я запускаю df[df.index.month==12], появляется 5 рядов

PTQuoc 06.05.2022 21:20

поскольку мы отправляем одну группу за раз, comp == 'a' имеет только 3 даты с месяцем как 12, следовательно, 3 строки значений

Mayur Dhage 06.05.2022 21:23

df[df.index.month==12].to_dict()['old_col'] относится ко всем данным, поэтому вы получаете 5 строк

Mayur Dhage 06.05.2022 21:36

Думаю, я понял. Еще один вопрос, я не понимаю ['new_col'] после apply, так как я никогда раньше не использовал его с groupby. (Этот, .apply(helper_func)['new_col']). Зачем нам нужен этот ['new_col'] и что он там делает? Можете ли вы помочь мне объяснить это немного?

PTQuoc 06.05.2022 21:38

это связано с тем, что [['old_col']] двойные скобки отправляют фрейм данных в groupby, следовательно, получают фрейм данных в качестве вывода. Итак, чтобы получить доступ только к «new_col» из результирующего фрейма данных после groupby , сделайте это

Mayur Dhage 06.05.2022 21:45

вы можете получить выходной фрейм данных, просто используя df.groupby('comp')[['old_col']].apply(helper_func), это будет фрейм данных

Mayur Dhage 06.05.2022 21:45

Это превосходно. Большое спасибо, ваши решения мне очень помогают. Я борюсь с shift со вчерашнего дня

PTQuoc 06.05.2022 21:55

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