2015-12-02 4 views
4

У меня два Dataframes один большой с большим количеством недостающих значений, а второй с данными, чтобы заполнить недостающие данные в первом.Как заполнить много данных utlizing pandas fillna быстро?

Dataframe примеры:

In[34]: 
import pandas as pd 
import numpy as np 

df2 = pd.DataFrame({'A': [1, 1, 1, 2, 2, 2], 'B': [1, 0, 1, 1, 0, 0]}) 

df = pd.DataFrame({'A': [0, 1, 2, 3, 4, 5], 'B1': [1, np.nan, np.nan, 8, 9, 1],'B2':[1, np.nan, np.nan, 7, 6, 1], 'B3':[1, np.nan, np.nan, 8, 7, 1] }) 
df=df.set_index(['A']) 
df2=df2.set_index(['A']) 

In[35]: 
df 

Out[35]: 
    B1 B2 B3 
A    
0 1 1 1 
1 NaN NaN NaN 
2 NaN NaN NaN 
3 8 7 8 
4 9 6 7 
5 1 1 1 

In[36]: 
df2 

Out[36]: 
    B 
A 
1 1 
1 0 
1 1 
2 1 
2 0 
2 0 

так, что я хочу сделать, это заполнить ДФ, используя данные из df2 также принимая во внимание, что B1 не B2, когда встретив второй инстанции в df2. См ниже требуемого выхода:

In[38]: 
df 

Out[38]: 
    B1 B2 B3 
A    
0 1 1 1 
1 1 0 1 
2 1 0 0 
3 8 7 8 
4 9 6 7 
5 1 1 1 

The Nans в B1, B2 и B3 для 1 и 2 были заполнены данными из df2. 1 0 1 для индекса 1 и 1 0 0 для индекса 2. Ниже мой неэффективен для реализации контура:

In[37]: 
count=1 
seen=[] 

for t in range(0, len(df2)): 
    if df2.index[t] not in seen: 
     count=1 
     seen.append(df2.index[t]) 
    else: 
     count=count+1 
    tofill=pd.DataFrame(df2.iloc[t]).transpose() 
    tofill_dict={"B"+str(count):tofill.B} 
    df=df.fillna(value=tofill_dict) 

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

ответ

1

Сначала вы не можете сбросить индекс df2.

Вы можете использовать попробовать groupby - каждая группа перенося с T, а затем fillnadf значениями df2:

import pandas as pd 
import numpy as np 

df2 = pd.DataFrame({'A': [1, 1, 1, 2, 2, 2], 'B': [1, 0, 1, 1, 0, 0]}) 

df = pd.DataFrame({'A': [0, 1, 2, 3, 4, 5], 'B1': [1, np.nan, np.nan, 8, 9, 1],'B2':[1, np.nan, np.nan, 7, 6, 1], 'B3':[1, np.nan, np.nan, 8, 7, 1] }) 
df=df.set_index(['A']) 
df2=df2.set_index(['A']) 

print df 
    B1 B2 B3 
A    
0 1 1 1 
1 NaN NaN NaN 
2 NaN NaN NaN 
3 8 7 8 
4 9 6 7 
5 1 1 1 
print df2 
    A B 
0 1 1 
1 1 0 
2 1 1 
3 2 1 
4 2 0 
5 2 0 
df2 = df2.groupby(df2.index).apply(lambda x: x.B.reset_index(drop=True).T) 
df2.columns = df.columns 
print df2 
    B1 B2 B3 
A    
1 1 0 1 
2 1 0 0  

df = df.fillna(df2) 
print df 

    B1 B2 B3 
A    
0 1 1 1 
1 1 0 1 
2 1 0 0 
3 8 7 8 
4 9 6 7 
5 1 1 1 

Может быть, если df = df.fillna(df2) не работает, можно использовать df = df.combine_first(df2). Это зависит от индекса.

+0

Как это работает? Я не могу сравнить это с вашим решением, потому что ошибка: 'NameError: глобальное имя 'toappend' не определен' – jezrael

+0

Спасибо за ваш ответ jezrael! Я исправил причину ошибки, извините. Я быстро проверил, и он работает при использовании 'df2 = df2.groupby (df2.index) .apply (lambda x: xBreset_index (drop = True) .T)' вместо 'df2 = df2.groupby ('A') .apply (lambda x: xBreset_index (drop = True) .T) '. Нужно тестировать на большом наборе данных, когда я возвращаюсь домой – HBX

+0

ОК, вы правы, но я думал, что вы сбросите индекс только для этого заполнения. Поэтому я хочу удалить эту операцию. Я редактирую ответ. – jezrael

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