使用约束字典查询 Pandas

Querying Pandas with a Dictionary of Constraints

我正试图用 pandas 在某些年份中抽出几个月。我有这样返回的约束 {month: year}.

 [{1: 2003},
 {2: 2008},
 {3: 2011},
 {4: 2012},
 {5: 2008},
 {6: 2008},
 {7: 2002},
 {8: 2006},
 {9: 2005},
 {10: 2013},
 {11: 2005},
 {12: 2001}]

意味着我想要数据框中的 2003 年 1 月、2008 年 2 月等。我有 "Month" 和 "Year" 作为数据框中的两列。

我想要一些东西来执行这个不正确的代码(但思路很明确):

df[(df['Month'] == key for key in dict) & (df['Year'] == dict[key])]

一个 hack* 方法是将年份和月份作为浮点数相加并使用:

In [11]: months = set(year + month * 0.01 for i in d for (month, year) in i.items())

In [12]: months
Out[12]: {2001.12, 2002.07, 2003.01, 2005.09, 2006.08, 2005.11, 2008.02, 2008.05, 2008.06, 2011.03, 2012.04, 2013.1}

然后检查 DataFrame 中是否有相同的 year.month:

In [21]: df = pd.DataFrame([[2001, 12], [2001, 3], [2002, 7]], columns=["Year", "Month"])

In [22]: df
Out[22]:
   Year  Month
0  2001     12
1  2001      3
2  2002      7

In [23]: (df["Year"] + 0.01 * df["Month"]).isin(months)
Out[23]:
0     True
1    False
2     True
dtype: bool

所以你想要的子帧是:

In [24]: df[(df["Year"] + 0.01 * df["Month"]).isin(months)]
Out[24]:
   Year  Month
0  2001     12
2  2002      7

*可以用但是感觉有点脏...

您可以使用 lambda 在 Pandas 中执行高级过滤。

假设:

  1. 所有月份和年份都是整数
  2. 约束在list of dict类型中

如果数据类型不同,您可以修改以下行以解决您的问题。

生成随机数据填充数据框

In [1]: from random import randint 

In [2]: months = [randint(1, 12) for x in range(10)]

In [3]: years = [randint(2000, 2020) for x in range(10)]

In [4]: months
Out[4]: [12, 3, 7, 6, 10, 10, 11, 9, 9, 10]

In [5]: years
Out[5]: [2017, 2016, 2001, 2004, 2015, 2013, 2001, 2020, 2013, 2016]

In [6]: import pandas as pd

In [7]: df = pd.DataFrame()

In [8]: df['Month'] = months

In [9]: df['Year'] = years

2。使用给定的 list of dict 并将其转换为 list of tuple 以便于编码

(注意:一旦你理解了我想要完成的事情,你可以根据需要更改你的约束。)

In [10]: filterDict = [{1: 2003}, {2: 2008}, {3: 2011}, {4: 2012}, {5: 2008}, {6: 2008}, {7: 2002}, {8: 2006}, {9: 2005}, {3: 2016}, {6: 2004}, {12: 2001}]

In [11]: filterList = [d.items()[0] for d in filterDict]

3。使用lambda过滤dataframe

In [12]: df[df.apply(lambda x: (x['Month'],x['Year']) in filterList, axis=1)]
Out[12]: 
   Month  Year
1      3  2016
3      6  2004

过滤前的原始数据供大家参考:

In [13]: df
Out[13]: 
   Month  Year
0     12  2017
1      3  2016
2      7  2001
3      6  2004
4     10  2015
5     10  2013
6     11  2001
7      9  2020
8      9  2013
9     10  2016
from functools import reduce
df = pandas.DataFrame(dict(col1=[1,2], col2=['a','b']))
   col1 col2
0     1    a
1     2    b
params = dict(col1=2, col2='b')
mask = reduce(lambda x,y: x & y, [df[k] == v for k,v in params.items()])
print(df[mask])

   col1 col2
1     2    b