2014-01-10 4 views
5

У меня есть неполный фрейм данных, incomplete_df, как показано ниже. Я хочу ввести недостающие amount s в среднем amount соответствующего id. Если среднее значение для этого конкретного id само является NaN (см. id=4), я хочу использовать общее среднее значение.Pandas: Impute NaN

Ниже приведены примеры данных и мой крайне неэффективным решение:

import pandas as pd 
import numpy as np 
incomplete_df = pd.DataFrame({'id': [1,2,3,2,2,3,1,1,1,2,4], 
           'type': ['one', 'one', 'two', 'three', 'two', 'three', 'one', 'two', 'one', 'three','one'], 
         'amount': [345,928,np.NAN,645,113,942,np.NAN,539,np.NAN,814,np.NAN] 
         }, columns=['id','type','amount']) 

# Forrest Gump Solution 
for idx in incomplete_df.index[np.isnan(incomplete_df.amount)]: # loop through all rows with amount = NaN 
    cur_id = incomplete_df.loc[idx, 'id'] 
    if (cur_id in means.index): 
     incomplete_df.loc[idx, 'amount'] = means.loc[cur_id]['amount'] # average amount of that specific id. 
    else: 
     incomplete_df.loc[idx, 'amount'] = np.mean(means.amount) # average amount across all id's 

Какой самый быстрый и самый вещий/pandonic путь для достижения этой цели?

+0

в 0.13 вы можете это сделать: http://pandas.pydata.org/pandas-docs/dev/missing_data.html#interpolation и увидеть раздел с отсутствующими значениями: http://pandas.pydata.org/pandas-docs /dev/missing_data.html#cleaning-filling-missing-data – Jeff

+0

@Jeff, спасибо. Однако у меня есть не таймеры. Таким образом, статистически я ищу условное назначение, а не (inter/extra). Как я могу справиться с ситуацией, когда среднее значение данного идентификатора само по себе является «NaN»? – Rhubarb

+0

см. Решение @DSM ниже, как его вопрос, что вы хотите. Но интерполяция CAN работает на Frames FYI; временные ряды не имеют значения. Их много вариантов. – Jeff

ответ

15

Правовая оговорка: Меня не интересует самое быстрое решение, но наиболее удобное.

Здесь, я думаю, что будет что-то вроде:

>>> df["amount"].fillna(df.groupby("id")["amount"].transform("mean"), inplace=True) 
>>> df["amount"].fillna(df["amount"].mean(), inplace=True) 

который производит

>>> df 
    id type amount 
0 1 one 345.0 
1 2 one 928.0 
2 3 two 942.0 
3 2 three 645.0 
4 2 two 113.0 
5 3 three 942.0 
6 1 one 442.0 
7 1 two 539.0 
8 1 one 442.0 
9 2 three 814.0 
10 4 one 615.2 

[11 rows x 3 columns] 

Есть много очевидных настроек в зависимости от, как именно вы хотите прикован процесс дележа идти.

+0

Спасибо, DSM, если у меня есть местозаполнитель, например. 0, на месте NaN, будет самый быстрый способ заменить все 0 в качестве NaN, а затем следовать вашему решению? (Я знаю, что положить 0 на место NaN - это глупая идея - увы, с чем мне приходится работать, это то, что у меня есть.) – Rhubarb

+1

Это, наверное, то, что я сделал бы. Использование NaN для представления недостающих данных выполняется довольно глубоко в пандах, поэтому самый простой способ сделать что-то обычно требует получения ваших данных в соответствии с этим. Я не знаю о самом быстром - вы можете использовать timeit для сравнения. Переключение 0s для NaNs будет как линейным, так и векторизованным в любом случае, поэтому оно не добавит много времени для выполнения. – DSM

+0

только для подтверждения, это две альтернативы, а не обе, необходимые для завершения одной операции? –

Смежные вопросы