Drop rows containing empty cells from a pandas DataFrame
我有一个通过解析一些excel电子表格创建的pd.DataFrame。 一列的单元格为空。 例如,以下是该列的频率输出,32320条记录的"租户"值缺失。
1 2 3 4 5 6 7 8 9 10 11 | In [67]: value_counts(Tenant,normalize=False) Out[67]: 32320 Thunderhead 8170 Big Data Others 5700 Cloud Cruiser 5700 Partnerpedia 5700 Comcast 5700 SDP 5700 Agora 5700 dtype: int64 |
我正在尝试删除缺少租户的行,但是isull选项无法识别丢失的值。
1 2 | In [71]: df['Tenant'].isnull().sum() Out[71]: 0 |
该列的数据类型为"对象"。 在这种情况下会发生什么? 如何在租户丢失的地方删除记录?
如果熊猫是
为了演示,我们在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | >>> import pandas as pd >>> import numpy as np >>> >>> df = pd.DataFrame(np.random.randn(10, 2), columns=list('AB')) >>> df['Tenant'] = np.random.choice(['Babar', 'Rataxes', ''], 10) >>> print df A B Tenant 0 -0.588412 -1.179306 Babar 1 -0.008562 0.725239 2 0.282146 0.421721 Rataxes 3 0.627611 -0.661126 Babar 4 0.805304 -0.834214 5 -0.514568 1.890647 Babar 6 -1.188436 0.294792 Rataxes 7 1.471766 -0.267807 Babar 8 -1.730745 1.358165 Rataxes 9 0.066946 0.375640 |
现在,我们将
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | >>> df['Tenant'].replace('', np.nan, inplace=True) >>> print df A B Tenant 0 -0.588412 -1.179306 Babar 1 -0.008562 0.725239 NaN 2 0.282146 0.421721 Rataxes 3 0.627611 -0.661126 Babar 4 0.805304 -0.834214 NaN 5 -0.514568 1.890647 Babar 6 -1.188436 0.294792 Rataxes 7 1.471766 -0.267807 Babar 8 -1.730745 1.358165 Rataxes 9 0.066946 0.375640 NaN |
现在我们可以删除空值:
1 2 3 4 5 6 7 8 9 10 11 | >>> df.dropna(subset=['Tenant'], inplace=True) >>> print df A B Tenant 0 -0.588412 -1.179306 Babar 2 0.282146 0.421721 Rataxes 3 0.627611 -0.661126 Babar 5 -0.514568 1.890647 Babar 6 -1.188436 0.294792 Rataxes 7 1.471766 -0.267807 Babar 8 -1.730745 1.358165 Rataxes |
默认情况下,value_counts省略NaN,因此您最有可能处理"。
所以你可以像这样过滤掉它们
1 2 | filter = df["Tenant"] !="" dfNew = df[filter] |
Pythonic + Pandorable:
空字符串是虚假的,这意味着您可以像这样过滤布尔值:
1 2 3 4 5 6 7 8 9 10 11 | df = pd.DataFrame({ 'A': range(5), 'B': ['foo', '', 'bar', '', 'xyz'] }) df A B 0 0 foo 1 1 2 2 bar 3 3 4 4 xyz |
1 2 3 4 5 6 7 8 9 10 11 12 13 | df['B'].astype(bool) 0 True 1 False 2 True 3 False 4 True Name: B, dtype: bool df[df['B'].astype(bool)] A B 0 0 foo 2 2 bar 4 4 xyz |
如果您的目标不仅是删除空字符串,而且还删除仅包含空格的字符串,请事先使用
1 2 3 4 5 | df[df['B'].str.strip().astype(bool)] A B 0 0 foo 2 2 bar 4 4 xyz |
比您想像的快
这是一个时序比较,我想了一些其他方法。
基准测试代码,以供参考:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import pandas as pd import perfplot df1 = pd.DataFrame({ 'A': range(5), 'B': ['foo', '', 'bar', '', 'xyz'] }) perfplot.show( setup=lambda n: pd.concat([df1] * n, ignore_index=True), kernels=[ lambda df: df[df['B'].astype(bool)], lambda df: df[df['B'] != ''], lambda df: df[df['B'].replace('', np.nan).notna()], # optimized 1-col lambda df: df.replace({'B': {'': np.nan}}).dropna(subset=['B']), ], labels=['astype',"!= ''","replace + notna","replace + dropna", ], n_range=[2**k for k in range(1, 15)], xlabel='N', logx=True, logy=True, equality_check=pd.DataFrame.equals) |
在某些情况下,单元格有空白,您看不到,请使用
1 | df['col'].replace(' ', np.nan, inplace=True) |
将空白替换为NaN,然后
1 | df= df.dropna(subset=['col']) |
您可以使用以下变体:
1 2 3 4 5 6 7 8 | import pandas as pd vals = { 'name' : ['n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7'], 'gender' : ['m', 'f', 'f', 'f', 'f', 'c', 'c'], 'age' : [39, 12, 27, 13, 36, 29, 10], 'education' : ['ma', None, 'school', None, 'ba', None, None] } df_vals = pd.DataFrame(vals) #converting dict to dataframe |
这将输出(**-仅突出显示所需的行):
1 2 3 4 5 6 7 8 | age education gender name 0 39 ma m n1 ** 1 12 None f n2 2 27 school f n3 ** 3 13 None f n4 4 36 ba f n5 ** 5 29 None c n6 6 10 None c n7 |
因此,要删除所有没有"教育"值的内容,请使用以下代码:
1 | df_vals = df_vals[~df_vals['education'].isnull()] |
("?"表示不)
结果:
1 2 3 4 | age education gender name 0 39 ma m n1 2 27 school f n3 4 36 ba f n5 |