我正在尝试像这样修复pandas DataFrame中缺少的行:
import pandas as pd
df = pd.DataFrame([[1, 1.2, 3.4], [2, 4.5, 6.7], [3, 1.3, 2.5], [4, 5.6, 7.3],
[1, 3.4, 5.8], [2, 5.7, 8.9], [4, 2.4, 2.6], [1, 6.7, 8.4],
[3, 6.9, 4.2], [4, 4.2, 1.2]], columns = ['#', 'foo', 'bar'])
上面的代码给了我这样的熊猫数据框:
Out[10]:
# foo bar
0 1 1.2 3.4
1 2 4.5 6.7
2 3 1.3 2.5
3 4 5.6 7.3
4 1 3.4 5.8
5 2 5.7 8.9
6 4 2.4 2.6
7 1 6.7 8.4
8 3 6.9 4.2
9 4 4.2 1.2
您可能已经注意到,'#'
列中的值以1, 2, 3, 4, 1, 2, 3, 4 ...
的形式重复出现,但是缺少一些值(在这种情况下,第6行和{{ 1}}在第8行之前)。 我的问题是:根据3
列的重复模式,大熊猫中是否有任何内置方法(函数)来填充此数据框中的缺失行?填充行可以是2
,也可以是填充行之前和/或之后的值的内插\外推\平均值。换句话说,我想要的是这样的:
'#'
我尝试将NaN
列设置为数据框的索引,并使用常规模式对其重新索引,而不会丢失值。但是问题是Out[16]:
# foo bar
0 1 1.2 3.4
1 2 4.5 6.7
2 3 1.3 2.5
3 4 5.6 7.3
4 1 3.4 5.8
5 2 5.7 8.9
6 3 NaN NaN
7 4 2.4 2.6
8 1 6.7 8.4
9 2 NaN NaN
10 3 6.9 4.2
11 4 4.2 1.2
不适用于重复的值。我知道我总是可以通过在行与行之间的循环中进行迭代来解决问题的,这是传统的方式,但是如果使用大数据,这恐怕会很耗时。
如果有人可以给我提示,我将不胜感激。
答案 0 :(得分:3)
您需要以某种方式创建组-这里使用值差异#
并与Series.le
比较>1
,然后将GroupBy.apply
与Series.reindex
比较:
df1 = (df.groupby(df['#'].diff().lt(1).cumsum())
.apply(lambda x: x.set_index('#').reindex(range(1, 5)))
.reset_index(level=0, drop=True)
.reset_index())
print (df1)
# foo bar
0 1 1.2 3.4
1 2 4.5 6.7
2 3 1.3 2.5
3 4 5.6 7.3
4 1 3.4 5.8
5 2 5.7 8.9
6 3 NaN NaN
7 4 2.4 2.6
8 1 6.7 8.4
9 2 NaN NaN
10 3 6.9 4.2
11 4 4.2 1.2
另一个想法是创建MultiIndex
并通过unstack
和stack
重塑形状:
df = (df.set_index(['#', df['#'].diff().lt(1).cumsum()])
.unstack()
.reindex(np.arange(4)+1)
.stack(dropna=False)
.sort_index(level=1)
.reset_index(level=1, drop=True)
.reset_index())
print (df)
# foo bar
0 1 1.2 3.4
1 2 4.5 6.7
2 3 1.3 2.5
3 4 5.6 7.3
4 1 3.4 5.8
5 2 5.7 8.9
6 3 NaN NaN
7 4 2.4 2.6
8 1 6.7 8.4
9 2 NaN NaN
10 3 6.9 4.2
11 4 4.2 1.2
答案 1 :(得分:3)
我们可以用1,2,3,4
和eq
标记cumsum
的每组。
然后我们groupby
在这些组上使用reindex
,最后concat
将它们重新组合在一起。
s = df['#'].eq(4).shift().cumsum().bfill()
pd.concat(
[d.set_index('#').reindex(np.arange(4)+1) for _, d in df.groupby(s)]
).reset_index()
输出
# foo bar
0 1 1.2 3.4
1 2 4.5 6.7
2 3 1.3 2.5
3 4 5.6 7.3
4 1 3.4 5.8
5 2 5.7 8.9
6 3 NaN NaN
7 4 2.4 2.6
8 1 6.7 8.4
9 2 NaN NaN
10 3 6.9 4.2
11 4 4.2 1.2
注意:如果您在4
列中缺少#
作为值,则此方法将失败。
答案 2 :(得分:1)
这与@jezrael的reindex
和sort_index
相似:
df['rep'] = df['#'].diff().le(0).cumsum()
(df.set_index(['rep','#'])
.unstack('#')
.stack('#', dropna=False)
.reset_index('#')
.reset_index(drop=True)
)
输出:
# foo bar
0 1 1.2 3.4
1 2 4.5 6.7
2 3 1.3 2.5
3 4 5.6 7.3
4 1 3.4 5.8
5 2 5.7 8.9
6 3 NaN NaN
7 4 2.4 2.6
8 1 6.7 8.4
9 2 NaN NaN
10 3 6.9 4.2
11 4 4.2 1.2