使用分组

时间:2016-12-06 17:26:39

标签: python pandas numpy

我正在寻找关于pandas中非常大的数据帧问题的解决方案。

我们假设我有一个非常大的数据帧,其中包含NA。我想用具有相同ID的行的平均值来填充NA。我知道有些ID与我无关(参见示例代码中的数组" ids")。

我想出了以下代码:

# relevant Ids
ids = [2,3]
# create example dataframe
test = pd.DataFrame([[1,1,4],[1,np.nan,np.nan],[1,3,5],[2,np.nan,3],[2,5,5],[2,7,np.nan],[3,4,np.nan],[3,np.nan,3],[3,8,9]],columns=['id','v1','v2'])
# fill NAs with the mean of the group defined by ID
test[test.id.isin(ids)] = pd.concat([test[test.id.isin(ids)].id,test[test.id.isin(ids)].groupby('id').transform(lambda x: x.fillna(x.mean()))],axis=1)

我在一个循环周围的环境中使用它。 在每个循环中,大约1000行将被添加到数据帧中,我必须为这些行填充NA。

这意味着,我可以从中获得的每一点性能都非常棒。我试图避免创建数据帧的副本,因为这似乎更慢。

也许有人有想法?我认为,例如,应该避免使用isin()三次过滤,但我无法在不复制数据帧的情况下找到解决方案。

我不是python或pandas的专家,所以可能会遗漏一些东西。

2 个答案:

答案 0 :(得分:1)

好像你做了很多工作。你不能先替换所有缺失的值,然后过滤

startnode.bat

还有一种没有变换的方法

test[['v1', 'v2']] = test.groupby('id').transform(lambda x: x.fillna(x.mean()))
test[test.id.isin(ids)]

答案 1 :(得分:1)

这是一个循环遍历列的NumPy解决方案 -

a = test.values
ID = a[:,0].astype(int)
for i in range(1,test.shape[1]):
    nan_mask = np.isnan(a[:,i])
    ids_i = np.intersect1d(ID[~nan_mask], ids) # Account for at least 1 NaN grp
    valid_mask = np.in1d(ID, ids_i)
    m1 = ~nan_mask & valid_mask
    m2 = nan_mask & valid_mask
    s1 = np.bincount(ID[m1],a[m1,i])/np.bincount(ID[m1])
    test.iloc[m2,i] = s1[ID[m2],None]