我有一个复杂的大型pandas数据框,其中一列X可以包含一个列表或一个列表列表。我很好奇,如果解决方案可以应用于任何内容,所以我给出一个模拟示例,其中X的一个元素也是一个字符串:
df1 = pd.DataFrame({
'A': [1, 1, 3],
'B': ['a', 'e', 'f'],
'X': ['something', ['hello'], [['something'],['hello']]]}
)
我想获得该数据帧的子集df2,其中列X包含子串“hello”,当其中的任何内容都以字符串形式读取时。
>>> df2
A B X
0 1 e [hello]
1 3 f [[something], [hello]]
我尝试了str()和.str.contains,apply,map,.find(),list comprehensions的广泛组合,似乎没有任何东西可以在没有进入循环的情况下工作(相关问题here和{{ 3}}。我错过了什么?
答案 0 :(得分:5)
在astype
str.contains
df1[df1.X.astype(str).str.contains('hello')]
Out[538]:
A B X
1 1 e [hello]
2 3 f [[something], [hello]]
答案 1 :(得分:4)
您可以使用np.ravel()展平嵌套列表并在运算符
中使用df1[df1['X'].apply(lambda x: 'hello' in np.ravel(x))]
A B X
1 1 e [hello]
2 3 f [[something], [hello]]
答案 2 :(得分:1)
借用@wim https://stackoverflow.com/a/49247980/2336654
最通用的解决方案是允许任意嵌套列表。此外,我们可以专注于字符串元素相等而不是包含。
# This import is for Python 3
# for Python 2 use `from collections import Iterable`
from collections.abc import Iterable
def flatten(collection):
for x in collection:
if isinstance(x, Iterable) and not isinstance(x, str):
yield from flatten(x)
else:
yield x
df1[df1.X.map(lambda x: any('hello' == s for s in flatten(x)))]
A B X
1 1 e [hello]
2 3 f [[something], [hello]]
所以现在如果我们复杂化
df1 = pd.DataFrame({
'A': [1, 1, 3, 7, 7],
'B': ['a', 'e', 'f', 's', 's'],
'X': [
'something',
['hello'],
[['something'],['hello']],
['hello world'],
[[[[[['hello']]]]]]
]}
)
df1
A B X
0 1 a something
1 1 e [hello]
2 3 f [[something], [hello]]
3 7 s [hello world]
4 7 s [[[[[['hello']]]]]]
我们的过滤器不会抓取hello world
并抓住非常嵌套的hello
df1[df1.X.map(lambda x: any('hello' == s for s in flatten(x)))]
A B X
1 1 e [hello]
2 3 f [[something], [hello]]
4 7 s [[[[[['hello']]]]]]