使用dict的值过滤多列上的pandas数据框以实现部分字符串匹配

时间:2018-10-28 14:07:06

标签: python pandas dataframe filter

我需要根据字典中的多个值过滤数据框

df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv')
filters_raw = {'continent': {'filterTerm': 'Asi', 'column': {'rowType': 'filter', 'key': 'continent', 'name': 'continent', 'editable': True, 'sortable': True, 'resizable': True, 'filterable': True, 'width': 147, 'left': 60}}, 'gdpPercap': {'filterTerm': '9', 'column': {'rowType': 'filter', 'key': 'gdpPercap', 'name': 'gdpPercap', 'editable': True, 'sortable': True, 'resizable': True, 'filterable': True, 'width': 147, 'left': 354}}, 'lifeExp': {'filterTerm': '4', 'column': {'rowType': 'filter', 'key': 'lifeExp', 'name': 'lifeExp', 'editable': True, 'sortable': True, 'resizable': True, 'filterable': True, 'width': 147, 'left': 501}}, 'pop': {'filterTerm': '3', 'column': {'rowType': 'filter', 'key': 'pop', 'name': 'pop', 'editable': True, 'sortable': True, 'resizable': True, 'filterable': True, 'width': 147, 'left': 648}}, 'year': {'filterTerm': '2007', 'column': {'rowType': 'filter', 'key': 'year', 'name': 'year', 'editable': True, 'sortable': True, 'resizable': True, 'filterable': True, 'width': 147, 'left': 795}}, 'country': {'filterTerm': 'af', 'column': {'rowType': 'filter', 'key': 'country', 'name': 'country', 'editable': True, 'sortable': True, 'resizable': True, 'filterable': True, 'width': 147, 'left': 207}}}
filters = {i:filters_raw[i]['filterTerm'] for i in filters_raw.keys()}

要使用字典来获得完全匹配,我可以这样做 基于此答案(Filter a pandas dataframe using values from a dict); ;

dff = df.loc[(df[list(filters)] == pd.Series(filters)).all(axis=1)]

但是,如果我想以相同的方式进行过滤,但不仅限于完全匹配,还可以获取匹配,其中dict中的值作为子字符串包含在数据帧中。我该怎么办?

所需的输出是一个仅具有同时与所有条件相对应的值的数据帧。使用上面的过滤器;

Dff
Asia Afghanistan 974.5803384 43.828 31889923 2007

2 个答案:

答案 0 :(得分:0)

看看pandas.Series.str.contains,您可以在其中使用正则表达式。还有string handling个函数可能会更适合您的需求。

答案 1 :(得分:0)

一种解决方案是使用pd.Series.str.starstwith查找与filters中的字符串匹配的字符串。

您可以通过以下方式为这些行创建掩码:

mask =  df.astype(str).apply(lambda x: x.str.lower()
        ).apply(lambda x: x.str.startswith(filters[x.name].lower()),
                axis=0).all(axis=1)

基本上,您可以将原始数据帧转换为字符串和小写字母,然后逐列检查该元素,该元素以该列的过滤器中的字符串开头(即filters['continent'])。最后,将所有单元格都包含filter

中的元素的行设置为true

结果将是:

df[mask]

        country  year         pop continent  lifeExp   gdpPercap
11  Afghanistan  2007  31889923.0      Asia   43.828  974.580338

希望它有用。