在Pandas中,如何根据值的类型过滤Series?

27

给定一个类似于Series的数据结构:

import pandas as pd

s = pd.Series(['foo', 'bar', 42])
我想获得一个“子系列”pd.Series(['foo','bar']),其中所有值都是字符串。我尝试了布尔索引,如下所示:

I would like to obtain a 'sub-series' pd.Series(['foo', 'bar']) in which all values are strings. I've tried Boolean indexing like so:


s[isinstance(s, str)]

但是这会产生一个

KeyError: False

到目前为止,在寻找合适的方法中,我遇到了select,但这对标签施加了一个条件,而不是对值。在这种情况下,如何基于(类型)值进行过滤?

3个回答

36

使用apply或者列表推导式:

s[s.apply(lambda x: isinstance(x, str))]

Jon Clements♦说的一样,谢谢:

s[s.apply(isinstance, args=(str,))]

s[[isinstance(x, str) for x in s]]

所有退回:

0    foo
1    bar
dtype: object

编辑:

这不是推荐的做法,感谢cᴏʟᴅsᴘᴇᴇᴅ的帮助:

s[s.apply(type) == str]

如果我是你,我会避免倡导使用 type(...) == ...,因为这不符合 Python 的风格。推荐使用 isinstance 来实现。 - cs95
是的,s[[isinstance(x, str) for x in s]]也在https://dev59.com/-1sW5IYBdhLWcg3wI0RH中提到。 - Kurt Peek
@cᴏʟᴅsᴘᴇᴇᴅ 这取决于您是否需要严格的字符串检查... 在 Python 2.x 中,对 basestring 进行 isinstance 检查是有意义的,例如... 这取决于您是否希望将任何继承自 str 的内容视为字符串。 - Jon Clements
@jezrael 我建议您在第一个示例中使用s.apply(isinstance, args=(str,)),避免使用lambda。 - Jon Clements
1
基本上,isinstance 也涵盖了继承层次结构。例如,isinstance(True, int) 是真的,但 type(True) == int 是假的。在 Python2 中,这尤其重要。因为 Unicode 和 str 被视为不同类型。你可以使用 isinstance(x, basestring) 来处理它,但不能像使用 type 那样简单。 - cs95
显示剩余2条评论

5
使用“pd.to_numeric”的小技巧:
s[pd.to_numeric(s, errors='coerce').isnull()]

0    foo
1    bar
dtype: object

如果一个项目是数字,它将成功强制转换(而不是 NaN),因此会从最终结果中删除。


2

如上所述,我会使用 pd.to_numeric

或者,您可以使用 str.isalpha

In [109]: s[s.str.isalpha().notnull()]
Out[109]:
0    foo
1    bar
dtype: object

1
我很好奇为什么非字符串类型的变量返回NaN而不是False,这是不一致的。 - cs95

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接