我有一个非常大的pandas数据集,其数据看起来像
df = pd.DataFrame({'group1' : ['A', 'A', 'A', 'A',
'B', 'B', 'B', 'B'],
'group2' : ['C', 'C', 'C', 'D',
'E', 'E', 'F', 'F'],
'B' : ['one', np.NaN, np.NaN, np.NaN,
np.NaN, 'two', np.NaN, np.NaN],
'C' : [np.NaN, 1, np.NaN, np.NaN,
np.NaN, np.NaN, np.NaN, 4]})
df
Out[64]:
B C group1 group2
0 one NaN A C
1 NaN 1 A C
2 NaN NaN A C
3 NaN NaN A D
4 NaN NaN B E
5 two NaN B E
6 NaN NaN B F
7 NaN 4 B F
您可以在此处看到,对于group1
和group2
的每个唯一组合,列B
和C
最多只包含一个非缺失变量。
在每个groupby(['group1','group2'])
组中,如果该值存在,则使用该唯一的非缺失值(在该组中)替换所有缺失值。
为此,我使用first
之后可用的groupby
函数,该函数将每个组中B或C的第一个非缺失值传播到该组中的其余缺失值:
df[['B','C']]=df.groupby(['group1','group2']).transform('first')
df
Out[62]:
B C group1 group2
0 one 1 A C
1 one 1 A C
2 one 1 A C
3 NaN NaN A D
4 two NaN B E
5 two NaN B E
6 NaN 4 B F
7 NaN 4 B F
不幸的是,在我非常大的数据集中,这是痛苦缓慢。你有没有办法提高速度?我在考虑fillna
,但似乎我需要应用它两次(ffill
和bfill
)......有什么想法吗?
更新下面ajcr
提出的非常有效的解决方案是否适用于由多个列定义的组? map
在这种情况下不起作用。也许merge
?
答案 0 :(得分:3)
在我的计算机上,使用groupby
然后map
的速度提高近100倍:
g = df.groupby('group', sort=False).first()
df['B'] = df['group'].map(g['B'])
df['C'] = df['group'].map(g['C'])
这是一个包含1000组和10000行的测试DataFrame:
df = pd.DataFrame({'group': np.repeat(np.arange(1000), 10),
'B': np.nan,
'C': np.nan})
df.ix[4::10, 'B':'C'] = 5 # every 4th row of a group is non-null
时间安排:
%%timeit
df2 = df.copy()
g = df2.groupby('group', sort=False).first()
df2['B'] = df2['group'].map(g['B'])
df2['C'] = df2['group'].map(g['C'])
返回100 loops, best of 3: 2.29 ms per loop
。
transform
方法慢了近100倍:
%%timeit
df3 = df.copy()
df3[['B','C']] = df3.groupby('group').transform('first')
返回1 loops, best of 3: 205 ms per loop
。
关于您关于使用多个群组的更新问题,@ jeff在以下评论中使用
的建议df['B'] = df.groupby(['group1','group2']).B.transform('first')
df['C'] = df.groupby(['group1','group2']).C.transform('first')
比一次转换两列快约50倍。这是因为目前transform
系列的性能要高得多,尽管newly-created issue也可以提高DataFrame上的操作速度。
答案 1 :(得分:1)
让我们加快一点:
In [130]: a = df.copy()
In [131]: %timeit a['B'],a['C'] = a.B.fillna(method='ffill'), a.C.fillna(method='bfill')
1000 loops, best of 3: 538 µs per loop
In [132]: a = df.copy()
In [133]: %timeit a[['B','C']]=a.groupby('A').transform('first')
100 loops, best of 3: 3 ms per loop
答案 2 :(得分:1)
如果你以不同的方式解决这个问题并且没有尝试填充,而是重建,那该怎么办?
unique_df = df.drop_duplicates()
bVal = unique_df.drop(['B'],axis = 1).dropna().set_index(['A'])
cVal = unique_df.drop(['C'],axis = 1).dropna().set_index(['A'])
colVals = pd.merge(bVal,cVal, how = 'outer',left_index = True, right_index = True)
output = pd.merge(df[['A']],colVals, how = 'left',left_on = 'A',right_index = True)
将df缩小到唯一的部分,在较小的数据帧上找到唯一的行,然后重新合并以重建更大的帧 - 更快?