用所有缺失的数据组合填充 list/pandas.dataframe(如 R 中的 complete() )

Posted

技术标签:

【中文标题】用所有缺失的数据组合填充 list/pandas.dataframe(如 R 中的 complete() )【英文标题】:Fill a list/pandas.dataframe with all the missing data combinations (like complete() in R) 【发布时间】:2016-10-26 05:09:59 【问题描述】:

我有如下数据集(这是一个例子,它实际上有 66k 行):

        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

我想用 0 填充所有缺失的组合(3-7 号房屋有多少香蕉?除了 5 号房屋还有多少辣椒?),得到如下结果:

        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

我知道 R 集成了 complete function。

现在我一直在处理从原始 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上?

【问题讨论】:

您可以发布所需的数据集吗?这将有助于了解你在追求什么...... 【参考方案1】:

您可以使用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')]

现在我们将使用itertools.product 为那些kinds 与房屋生成所有对。

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_indexreindex 来获取缺失的观察结果。

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]

【讨论】:

完整的笛卡尔积是正确的做法吗?似乎它会在TypeFood 之间提供额外的组合。例如:(Fruit, Banana, House-1)(Vegetable, Banana, House-1)(Seasoning, Banana, House-1) 都将是索引值,但似乎只有第一个是需要的。而不是完整的笛卡尔积Type X Food X Loc,我认为它应该是[Type, Food] X Loc,如果这有意义的话。或者,也许我只是对样本数据读得太多了? 什么是k? x[0] 和 x[1] 是什么? 抱歉,k 应该是 kinds,但我错过了。 x[0] 和 x[1]` 正在从各种元组中解包元组。我已经编辑它以使用命名元组,所以希望现在更清楚了。 这几乎很棒!唯一的(大)问题:每种食物都被复制了与可用数据点一样多的次数。例如,我有两次关于香蕉房屋 1 的信息(因为我有两个香蕉数据点)。可能是什么问题?编辑:这是重新索引功能:/ 您可能可以使用 groupby df.groupby(['Type', 'Food', 'Loc']).Num.sum() 预处理那些。或者你需要一个额外的observation_number 列来跟踪它【参考方案2】:

这应该可行:

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)

【讨论】:

以上是关于用所有缺失的数据组合填充 list/pandas.dataframe(如 R 中的 complete() )的主要内容,如果未能解决你的问题,请参考以下文章

R语言-均值填充缺失值

如何用其他数据框的值填充缺失值

用替换数据填充缺失数据

pandas使用replace函数将所有的无穷大值np.inf替换为缺失值np.nan使用pandas的fillna函数用经验固定值填充缺失值np.nan

Netezza SQL:用最近的数据填充缺失值

用之前的非缺失值填充缺失的 pandas 数据,按 key 分组