从第一个字母为小写的数据框中删除行

时间:2018-05-30 08:31:21

标签: python string python-3.x pandas dataframe

我有一个像 -

这样的数据框
    FileName        PageNo     LineNo   EntityName  
1   17743633 - 1    TM000002    69      Ambuja Cement Limited
2   17743633 - 1    TM000003    14      Vessel Name
3   17743633 - 1    TM000003    12      tyre Chips (Shredded Tyres)
4   17743633 - 1    TM000006    22      ambuja Cement Limited
5   17743633 - 1    TM000006    28      Binani Cement Limited

我必须从EntityName列首字母为小写的数据框中删除这些行。即我必须保留以大写字母开头的值。

到目前为止,我已经习惯了方法 -

df['EntityName'] = map(lambda x: x[0].isupper(), df['EntityName'])

但是它给出了NaN值。

我尝试的另一件事是正则表达式。

df['EntityName'] = df['EntityName'].str.replace('^[a-z]+$','')

但是没有效果。

另一个是 -

qw = df.EntityName.str[0]
df = df[qw.isupper()]

但显示错误 -

  

'系列'对象没有属性' isupper'

有人可以向我推荐正确的代码段或任何类型的提示吗?

4 个答案:

答案 0 :(得分:5)

首先通过索引选择第一个字母,然后选中isupperislower并按boolean indexing过滤:

df = df[df['EntityName'].str[0].str.isupper()]
#for working with NaN and None
#df = df[df['EntityName'].str[0].str.isupper().fillna(False)]

或者:

df = df[~df['EntityName'].str[0].str.islower()]
#for working with NaN and None
df = df[~df['EntityName'].str[0].str.islower().fillna(False)]

或者使用带有正则表达式的str.contains - ^用于匹配字符串的第一个值:

df = df[df['EntityName'].str.contains('^[A-Z]+')]

如果数据中没有NaN是列表理解,则解决方法:

df = df[[x[0].isupper() for x in df['EntityName']]]

使用空字符串和NaN的更常规解决方案是添加if-else

mask = [x[0].isupper() if isinstance(x,str) and len(x)>0 else False for x in df['EntityName']]
df = df[mask]
print (df)
              FileName          ...                       EntityName
1 17743633 -         1          ...            Ambuja Cement Limited
2 17743633 -         1          ...                      Vessel Name
5 17743633 -         1          ...            Binani Cement Limited

答案 1 :(得分:2)

您可以使用:

df[df.EntityName.str[0].str.isupper()]

答案 2 :(得分:2)

查看数据我认为istitle会做你的工作,即

df[df['EntityName'].str.istitle()]

      FileName    PageNo  LineNo             EntityName
1  17743633 - 1  TM000002      69  Ambuja Cement Limited
2  17743633 - 1  TM000003      14            Vessel Name
5  17743633 - 1  TM000006      28  Binani Cement Limited

答案 3 :(得分:0)

为了提高性能,请考虑使用简单的列表推导进行索引并访问系列的numpy数组表示:

df = df[[i[0].isupper() for i in df['EntityName'].values]]

如果您不希望系列中出现任何空字符串,则此解决方案将起作用。

效果基准

from operator import itemgetter, methodcaller

s = pd.Series(['Hello', 'hello', 'test', 'Test'])

def jpp(s):
    return list(map(methodcaller('isupper'), map(itemgetter(0), s.values)))

def jpp2(s):
    return [i[0].isupper() for i in s.values]

def jez(s):
    return s.str[0].str.isupper()

s = pd.concat([s]*100000)

%timeit jpp(s)   # 116 ms per loop
%timeit jpp2(s)  # 82 ms per loop
%timeit jez(s)   # 313 ms per loop