Группировка интерполяции Pandas с 3 столбцами

У меня есть следующие данные

data = {
    'Subject': ['3','3','3','3','3','3','3','3','3','10','10','10','10','10','10','10','10','10'],
    'Day': [1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    'Value': [19.0959, 19.2321, 19.3088, 19.2589, 19.3085, 19.0455, 19.3491, NaN, 19.1823, 25.7506, 25.8287, NaN, 26.2913, NaN, 26.1501, 25.9447, 25.9493, 25.9629]
}

который становится этим фреймом данных после pd.DataFrame(data):

   Subject   Day    Value
0        3     1  19.0959
1        3     2  19.2321
2        3     3  19.3088
3        3     4  19.2589
4        3     5  19.3085
5        3     6  19.0455
6        3     7  19.3491
7        3     8      NaN
8        3     9  19.1823
9       10     1  25.7506
10      10     2  25.8287
11      10     3      NaN
12      10     4  26.2913
13      10     5      NaN
14      10     6  26.1501
15      10     7  25.9447
16      10     8  25.9493
17      10     9  25.9629

Я попытался интерполировать недостающие данные в столбце «Значение», но этот фрейм данных, состоящий из 3 столбцов, похоже, вызывает проблемы, связанные с тем, что данные не интерполируются должным образом внутри групп, когда задействован НАМНОГО БОЛЬШОЙ фрейм данных со многими другими субъектами.

Например:

df['Value'] = df.groupby('Subject')['Value'].transform(lambda group: group.interpolate())

работает для небольших наборов данных, подобных показанному, но всякий раз, когда я применяю один и тот же код для замены NaN интерполяцией, когда имеется 1000 разных субъектов, каждый из которых имеет значения данных по 9 дней, есть случаи для субъекта 10, когда день 5 все еще остается NaN после интерполяции. Есть какие-нибудь советы по этому поводу? Спасибо!

Почему в 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
0
56
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

По умолчанию для параметра limit_direction установлено значение вперед. Это означает, что если первый элемент в серии — nan, он не будет интерполирован.

Учитывая слегка измененный фрейм данных:

>>> df
   Subject  Day    Value
0        3    1  19.0959
1        3    2  19.2321
2        3    3  19.3088
3        3    4  19.2589
4        3    5  19.3085
5        3    6  19.0455
6        3    7  19.3491
7        3    8      NaN
8        3    9  19.1823
9       10    1      NaN
10      10    2  25.8287
11      10    3      NaN
12      10    4  26.2913
13      10    5      NaN
14      10    6  26.1501
15      10    7  25.9447
16      10    8  25.9493
17      10    9  25.9629
>>> df['Value'] = df.groupby('Subject')['Value'].transform(lambda group: group.interpolate())
>>> df
   Subject  Day    Value
0        3    1  19.0959
1        3    2  19.2321
2        3    3  19.3088
3        3    4  19.2589
4        3    5  19.3085
5        3    6  19.0455
6        3    7  19.3491
7        3    8  19.2657
8        3    9  19.1823
9       10    1      NaN
10      10    2  25.8287
11      10    3  26.0600
12      10    4  26.2913
13      10    5  26.2207
14      10    6  26.1501
15      10    7  25.9447
16      10    8  25.9493
17      10    9  25.9629

Если мы повторим упражнение с приведенным выше фреймом данных и воспользуемся limit_direction='both', мы получим:

[...dataframe omitted...]
>>> df['Value'] = df.groupby('Subject')['Value'].transform(lambda group: group.interpolate(limit_direction='both'))
>>> df
   Subject  Day    Value
0        3    1  19.0959
1        3    2  19.2321
2        3    3  19.3088
3        3    4  19.2589
4        3    5  19.3085
5        3    6  19.0455
6        3    7  19.3491
7        3    8  19.2657
8        3    9  19.1823
9       10    1  25.8287
10      10    2  25.8287
11      10    3  26.0600
12      10    4  26.2913
13      10    5  26.2207
14      10    6  26.1501
15      10    7  25.9447
16      10    8  25.9493
17      10    9  25.9629

Подробности см. в документации по интерполяции Pandas.

---- Дополнение ----

Был дополнительный вопрос, который намекнул на тот факт, что данные не всегда могут быть отсортированы по дням. В этом случае просто отсортируйте его перед группировкой, как показано в следующем примере (см. обратный порядок для Субъекта 10):

>>> data2 = {
...     'Subject': ['3','3','3','3','3','3','3','3','3','10','10','10','10','10','10','10','10','10'],
...     'Day': [1, 2, 3, 4, 5, 6, 7, 8, 9, 2, 1, 3, 4, 5, 6, 7, 8, 9],
...     'Value': [19.0959, 19.2321, 19.3088, 19.2589, 19.3085, 19.0455, 19.3491, NaN, 19.1823, NaN,
25.8287, 26.0, 26.2913, NaN, 26.1501, 25.9447, 25.9493, 25.9629]
... }
>>> df2['Value'] = df2.sort_values(axis=0, by=['Subject', 'Day']).groupby('Subject')['Value'].transform(lambda group: group.interpolate(limit_direction='both'))
>>> df2
   Subject  Day     Value
0        3    1  19.09590
1        3    2  19.23210
2        3    3  19.30880
3        3    4  19.25890
4        3    5  19.30850
5        3    6  19.04550
6        3    7  19.34910
7        3    8  19.26570
8        3    9  19.18230
9       10    2  25.91435
10      10    1  25.82870
11      10    3  26.00000
12      10    4  26.29130
13      10    5  26.22070
14      10    6  26.15010
15      10    7  25.94470
16      10    8  25.94930
17      10    9  25.96290

Почему это работает? Давайте посмотрим на следующий образец:

>>> list(df2.sort_values(axis=0, by=['Subject', 'Day']).groupby('Subject')['Value'])
[('10', 10    25.82870
9     25.91435
11    26.00000
12    26.29130
13    26.22070
14    26.15010
15    25.94470
16    25.94930
17    25.96290
Name: Value, dtype: float64), ('3', 0    19.0959
1    19.2321
2    19.3088
3    19.2589
4    19.3085
5    19.0455
6    19.3491
7    19.2657
8    19.1823
Name: Value, dtype: float64)]

Здесь мы получили приведенный выше фрейм данных, отсортированный по теме и дню. Вы видите группу по, '10' и '3', а также перед столбцом Values видите индекс исходного фрейма данных (25,82870 соответствует индексу 10 исходного фрейма данных и т. д.), который затем используется для присвоения значений обратно в исходный фрейм данных в задании df2['Value'] = выше.

Другой вопрос: поскольку вы уже сортируете большую таблицу, хотите ли вы сохранить новый отсортированный порядок и, следовательно, реализовать это немного по-другому, но это зависит от вашего конкретного варианта использования...

Когда этот фрейм данных является частью более крупного фрейма данных с тысячами других субъектов со столбцами одного и того же дня (1-9, как в примере), и я следую этому методу, это работает, но интерполируемые значения не совпадают. Например, Субъект 10, день 3 не возвращается в 26.0600. Вместо этого я получаю что-то вроде 25,8322. Почему возникает такая разница?

F_pandas_groupby 02.06.2024 22:47

Это как если бы интерполяция различалась всякий раз, когда набор данных больше, несмотря на то, что интерполяция происходит через pandas.groupby. Разве в этом случае он не распознает столбец «День» как ориентир между двумя точками для интерполяции?

F_pandas_groupby 02.06.2024 22:53

Это немного сложно, не видя большего набора данных. Я сомневаюсь, что здесь учитывается столбец Day, и я думаю, что ваш набор данных не так хорошо отсортирован по дням, как в образце, который вы предоставили в своем вопросе. Я также добавил этот случай в свой ответ.

Tom 02.06.2024 23:46

Вы можете установить аргумент limit_direction на 'both' (см. документацию), чтобы гарантировать, что в столбце не останется значений NaN.

df.interpolate(method='linear', limit_direction='both', axis=0)

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