【问题标题】:Querying Pandas with a Dictionary of Constraints使用约束字典查询 Pandas
【发布时间】:2016-02-23 17:25:06
【问题描述】:

我正试图在特定年份与熊猫一起抽出几个月。我有这样返回的约束{月:年}。

 [{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 月等。我将“月”和“年”作为数据框中的两列。

我想要执行这个错误代码的东西(但想法很明确):

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

【问题讨论】:

  • 你的字典是这样的吗?你实际上已经粘贴了上面的字典列表。

标签: python pandas data-cleaning


【解决方案1】:

您可以使用 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 过滤数据框

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

【讨论】:

    【解决方案2】:

    这样做的一个技巧*是将年份和月份加起来作为浮点数并使用它:

    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}
    

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

    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
    

    *它可以工作,但感觉有点脏......

    【讨论】:

      【解决方案3】:
      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-02-06
        • 2020-09-07
        • 1970-01-01
        • 1970-01-01
        • 2018-06-21
        • 1970-01-01
        • 2021-08-17
        相关资源
        最近更新 更多