2016-10-04 55 views
1

一个非常基本的qs家伙 - thans vm用于查看。我想删除Col1中包含任何字符串的行 - 仅关注Col1中的数值。熊猫删除任何字符串的行

输入:

 Col1 Col2 Col3 
0  123 48.0 ABC 
1  45 85.0 DEF 
2 A.789 66.0 PQR 
3 RN.35 9.0 PQR 
4  LMO 12.0 ABC 

输出:

 Col1 Col2 Col3 
0 123.0 48.0 ABC 
1  45.0 85.0 DEF 

我试图

test = input_[input_['Col1'].str.contains(r'ABCDEGGHIJKLMNOPQRSTUVWXYZ.')] 

但是看到这个错误

ValueError: cannot index with vector containing NA/NaN values

您可以:

  • 给出一个简短的解释,为什么这是行不通的?
  • 什么是备用解决方案?

回答

4

这样做:

import re 
regex = re.compile("[a-zA-Z]+") 
df.ix[df.col1.map(lambda x: regex.search(x) is None)] 
+0

所以我没有这样的: 'input_.ix [input_.Col1.map(拉姆达X:regex.search(x)是无)]' 并得到错误: 'TypeError:预期的字符串或缓冲区' – spiff

+1

因为我不知道col1的类型,所以我认为它是字符串并执行该过程。如果不是,它会引发这样的例外。你可以这样做: df.ix [df.col1.map(lambda x:regex.search(str(x))is None)] 将col1转换为字符串类型并再次运行。 – Howardyan

+0

热潮!这是做到了 - 谢谢vm。我可以问你为什么我的方式不起作用吗? – spiff

2

boolean indexing和条件与to_numeric其中参数errors='coerce'意味着如果数据不是数字转换为NaN另一种更快的解决方案 - 因此你需要找到所有notnullNaN数据:

print (pd.to_numeric(df.Col1, errors='coerce')) 
0 123.0 
1  45.0 
2  NaN 
3  NaN 
4  NaN 
Name: Col1, dtype: float64 

print (pd.to_numeric(df.Col1, errors='coerce').notnull()) 
0  True 
1  True 
2 False 
3 False 
4 False 
Name: Col1, dtype: bool 

df = df[pd.to_numeric(df.Col1, errors='coerce').notnull()] 
print (df) 
    Col1 Col2 Col3 
0 123 48.0 ABC 
1 45 85.0 DEF 

时序

#[100000 rows x 3 columns]  
df = pd.concat([df]*10000).reset_index(drop=True) 

In [16]: %timeit (df.ix[df.Col1.map(lambda x: re.compile("[a-zA-Z]+").search(x) is None)]) 
10 loops, best of 3: 57.7 ms per loop 

In [17]: %timeit (df[pd.to_numeric(df.Col1, errors='coerce').notnull()]) 
10 loops, best of 3: 22 ms per loop 

In [18]: %timeit (df[~df['Col1'].astype(str).str.contains(r'[ABCDEGGHIJKLMNOPQRSTUVWXYZ.]', na=False)]) 
10 loops, best of 3: 38.8 ms per loop 

您的解决方案:

我想你需要转换为strastype,然后添加[]used to indicate a set of characters和最后的附加参数na=False,因为它似乎有些NaN值是col1,然后被转换成False

print (df['Col1'].astype(str).str.contains(r'[ABCDEGGHIJKLMNOPQRSTUVWXYZ.]', na=False)) 
0 False 
1 False 
2  True 
3  True 
4  True 
Name: Col1, dtype: bool 

然后需要通过~反转布尔掩码,并使用boolean indexing

print (df[~df['Col1'].astype(str).str.contains(r'[ABCDEGGHIJKLMNOPQRSTUVWXYZ.]', na=False)]) 
    Col1 Col2 Col3 
0 123 48.0 ABC 
1 45 85.0 DEF 
+0

非常感谢你的详细解答! – spiff

+0

我还添加了您的解决方案的时间安排,接受的解决方案的速度更快;) – jezrael