2013-07-09 3 views
1

Есть ли удобный способ заполнения значений na с помощью (первых) значений массива или столбца?Pandas fillna со списком/массивом

Представьте себе следующую DataFrame:

dfcolors = pd.DataFrame({'Colors': ['Blue', 'Red', np.nan, 'Green', np.nan, np.nan, 'Brown']}) 

    Colors 
0 Blue 
1 Red 
2 NaN 
3 Green 
4 NaN 
5 NaN 
6 Brown 

Я хочу, чтобы заполнить NaN значения со значениями из другого DataFrame или массива, так:

dfalt = pd.DataFrame({'Alt': ['Cyan', 'Pink']}) 

      Alt 
0   Cyan 
1   Pink 

Когда есть более Нэн то заполнить некоторые значения NaN должны оставаться. И когда будет больше значений заполнения, не все они будут использоваться. Таким образом, мы должны сделать некоторые подсчета:

n_missing = len(dfcolors) - dfcolors.count().values[0]  
n_fill = min(n_missing, len(dfalt)) 

Число n_fill это количество значений, которые могут быть заполнены.

Выбор значения NaN, которые могут/должны быть заполнены может быть сделано с:

dfcolors.Colors[pd.isnull(dfcolors.Colors)][:n_fill] 

2 NaN 
4 NaN 
Name: Colors, dtype: object 

Выбор заливку значения

dfalt.Alt[:n_fill] 

0 Cyan 
1 Pink 
Name: Alt, dtype: object 

И их я застрял на что-то вроде:

dfcolors.Colors[pd.isnull(dfcolors.Colors)][:n_fill] = dfalt.Alt[:n_fill] 

Который не работает ... Любые советы были бы замечательными.

Это вывод, что я хочу: значения

Colors 
0 Blue 
1 Red 
2 Cyan 
3 Green 
4 Pink 
5 NaN 
6 Brown 

NaN заполняется сверху вниз, а значения заполнения также выбирается сверху вниз, если есть более заполнить значения, чем Нэн

+1

Какой результат вы хотите? –

+0

Хорошо, я немного изменил вопрос. –

+0

Это [возврат к копиям] (http://pandas.pydata.org/pandas-docs/dev/indexing.html#indexing-view-versus-copy) (причудливая индексация всегда возвращает копию) ... hmm –

ответ

2

Это довольно ужасно, но итерация индекса нулей работа:

In [11]: nulls = dfcolors[pd.isnull(dfcolors['Colors'])] 

In [12]: for i, ni in enumerate(nulls.index[:len(dfalt)]): 
      dfcolors['Colors'].loc[ni] = dfalt['Alt'].iloc[i] 

In [13]: dfcolors 
Out[13]: 
    Colors 
0 Blue 
1 Red 
2 Cyan 
3 Green 
4 Pink 
5 NaN 
6 Brown 
3

Вы можете использовать генератор. Таким образом, вы можете написать примерно следующее:

import pandas as pd 
from pandas import np 

dfcolors = pd.DataFrame({'Colors': ['Blue', 'Red', np.nan, 'Green', np.nan, np.nan, 'Brown']}) 
dfalt = pd.DataFrame({'Alt': ['Cyan', 'Pink']}) 

gen_alt = (alt for alt in dfalt.Alt) 

for i, color in enumerate(dfcolors.Colors): 
    if not pd.isnull(color): continue 
    try: 
     dfcolors.Colors[i] = gen_alt.next() 
    except StopIteration: 
     break 
print(dfcolors) 
#  Colors 
# 0 Blue 
# 1 Red 
# 2 Cyan 
# 3 Green 
# 4 Pink 
# 5 NaN 
# 6 Brown