2016-06-23 7 views
2

У меня есть набор данных, как следующее (это пример, он на самом деле имеет 66K строк):Заполните список/pandas.dataframe со всеми отсутствующими комбинаций данных (например, полная() в R)

 Type  Food  Loc Num 
0  Fruit  Banana House-1 15 
1  Fruit  Banana House-2 4 
2  Fruit  Apple House-2 6 
3  Fruit  Apple House-3 8 
4 Vegetable Broccoli House-3 8 
5 Vegetable Lettuce House-4 12 
6 Vegetable Peppers House-5 3 
7 Vegetable  Corn House-4 4 
8 Seasoning Olive Oil House-6 2 
9 Seasoning Vinegar House-7 2 

Я хотел бы заполнить все недостающие комбинации (сколько бананов есть в домах 3-7?), Сколько перцев есть в другом месте, чем Дом-5?) С 0.

Я знаю, что R имеет эту функцию интегрировано: http://rpackages.ianhowson.com/cran/tidyr/man/complete.html

Прямо сейчас я работал ng со списком, который был переварен из исходного DataFrame, который я преобразовал в словарь.

for key,grp in fruit.groupby(level=0): 
     dir[key] = test.ix[key].values.tolist() 

fruit = {'Banana':[[1.0,15.0],[2.0,4.0], 
'Apple':[[2.0,6.0],[3.0,8.0] 

#Type = {fruit1:[[Loc1,Count1],...,[Locn],[Countn], 
#... fruitn:[...]} 

Я разработал эту функцию, чтобы применить к правилу ассигнационной словаря:

def fill_zeros(list): 
     final = [0]*127 
     for i in list: 
       final[int(i[0])] = i[1] 
     return final 

Это работает на отдельные «плоды»

print fill_zeros(test.ix['QLLSEEEKK'].values.tolist()) 
print fill_zeros(test.ix['GAVPLEMLEIALR'].values.tolist()) 
print fill_zeros(test.ix['VPVNLLNSPDCDVK'].values.tolist()) 

Но не по словарю

for key,grp in test.groupby(level=0): 
     dir[key] = fill_zeros(test.ix[key].values.tolist()) 

Traceback (most recent call last): 
    File "peptidecount.py", line 59, in <module> 
    print fill_zeros(test.ix[str(key)].values.tolist()) 
    File "peptidecount.py", line 43, in fill_zeros 
    final[int(i[0])] = i[1] 
TypeError: 'float' object has no attribute '__getitem__' 

По-видимому, я не правильно повторяю словарь. Есть ли способ исправить это? Или существует ли более подходящая функция для непосредственного применения к DataFrame? Благодарю вас

EDIT: Требуемый набор данных:

 Type  Food  Loc Num 
0  Fruit  Banana House-1 15 
1  Fruit  Banana House-2 4 
2  Fruit  Banana House-3 0 
... fill remaining houses with zeros 
6  Fruit  Banana House-7 0 
7  Fruit  Apple House-1 0 
8  Fruit  Apple House-2 6 
9  Fruit  Apple House-3 8 
... fill remaining houses with zeros 
14 Vegetable Broccoli House-1 0 
15 Vegetable Broccoli House-2 0 
16 Vegetable Broccoli House-3 8 
... etc  
n Seasoning Vinegar House-7 2 

ли кто-нибудь имеет представление о том, как установить функцию я использовал? Или это просто не стоит?

+2

Вы можете разместить требуемый набор данных? Это поможет понять, что вы после ... – MaxU

ответ

2

Вы можете использовать reindex.

Для начала вам понадобится список допустимых (type, food) пар. Я получу его из самих данных, вместо того, чтобы писать их.

In [88]: kinds = list(df[['Type', 'Food']].drop_duplicates().itertuples(index=False)) 

In [89]: kinds 
Out[89]: 
[('Fruit', 'Banana'), 
('Fruit', 'Apple'), 
('Vegetable', 'Broccoli'), 
('Vegetable', 'Lettuce'), 
('Vegetable', 'Peppers'), 
('Vegetable', 'Corn'), 
('Seasoning', 'Olive Oil'), 
('Seasoning', 'Vinegar')] 

Теперь мы создадим все пары для тех, kinds с домами с использованием itertools.product.

In [93]: from itertools import product 

In [94]: houses = ['House-%s' % x for x in range(1, 8)] 

In [95]: idx = [(x.Type, x.Food, house) for x, house in product(kinds, houses)] 

In [96]: idx[:2] 
Out[96]: [('Fruit', 'Banana', 'House-1'), ('Fruit', 'Banana', 'House-2')] 

И теперь вы можете использовать set_index и reindex, чтобы получить недостающие наблюдения.

In [98]: df.set_index(['Type', 'Food', 'Loc']).reindex(idx, fill_value=0) 
Out[98]: 
          Num 
Type  Food Loc 
Fruit  Banana House-1 15 
        House-2 4 
        House-3 0 
        House-4 0 
        House-5 0 
...      ... 
Seasoning Vinegar House-3 0 
        House-4 0 
        House-5 0 
        House-6 0 
        House-7 2 

[56 rows x 1 columns] 
+0

Является ли полный декартовой продукт правильной вещью? Похоже, что это даст дополнительные комбинации между 'Type' и' Food'. Пример: '(Fruit, Banana, House-1)', '(Vegetable, Banana, House-1)' и '(Seasoning, Banana, House-1)' будут все значения индекса, но только первое кажется было бы желательно. Вместо полного декартового продукта «Type X Food X Loc», я думаю, что это должно быть «[Type, Food] X Loc», если это имеет смысл. Или, может быть, я просто слишком много читаю в данных образца? – root

+0

Правильно, я пропустил это. Будет редактировать исправление. – TomAugspurger

+0

Что такое k? Что такое x [0] и x [1]? – Nico

0

Это должно работать:

cond0 = df.Num.isnull() 
cond1 = df.Food == 'Banana' 
cond2 = df.Loc.str.match(r'House-[34567]') 
cond3 = df.Food == 'Peppers' 
cond4 = df.Loc != 'House-5' 

missing_bananas = cond0 & cond1 & cond2 
missing_peppers = cond0 & cond3 & cond4 
missing_food = missing_bananas | missing_peppers 

df.loc[missing_food] = df.loc[missing_food].fillna(0)