【问题标题】:Pandas Integer FilteringPandas 整数过滤
【发布时间】:2019-01-28 04:25:55
【问题描述】:

我使用我创建的函数制作了一个数据框

data = generate_xml()

然后,我根据列名制作数据框的子集,在本例中称为 WalmartIDS 和 ASINS。下面也是数据框的示例

walmartIDS = data.loc[:,['WalmartIDS','ASINS']]

>>
    WalmartIDS  ASINS
602 20511489    B077BS6737
603 10311487    B077BMHVG7
604 10311302    B077BRTYCS
605 152381151   B077YW9PTQ
606 The-Holiday-Aisle-Projection-Kaleidoscope-Spider-Airblown-Inflatable-            Halloween-Decoration-THDA5581.html B076CNN6K5
607 51409868    B0756DMVSC
608 51410962    B0756FKLCV
609 51411020    B0756F3F6J
610 51411529    B0756FDM74
611 915505165   B076W25SDZ
612 400796633   B076VM75ZF

如您所见,有时不良数据会进入 WalmartIDS 列。因此,我想通过删除新创建的 walmartIDS 数据框中的所有行来过滤掉它,其中 WalmartIDS 列包含整数以外的字符。我不想更改数据框的数据版本,因为它是原始数据。

walmartIDS[walmartIDS.WalmartIDS != '^[-+]?[0-9]+$']

但是,上面的解决方案似乎没有做任何事情,实际上我仍然可以看到应该删除的坏数据(在示例中为第 606 行)。

这样做的正确方法是什么?

【问题讨论】:

    标签: python pandas filtering


    【解决方案1】:

    您需要使用正则表达式 (re):

    import re
    walmartIDS[re.match(r'^[-+]?[0-9]+$', walmartIDS.WalmartIDS) is not None]
    

    【讨论】:

    • 当我尝试这个时,我得到以下错误:TypeError: expected string or bytes-like object
    【解决方案2】:

    复制一份,转成数字,去掉na:

    测试数据:

    data = StringIO("""
    
    Walmart  IDS         ASINS
    602 20511489    B077BS6737
    603 10311487    B077BMHVG7
    604 10311302    B077BRTYCS
    605 152381151   B077YW9PTQ
    606 The-Holiday-Aisle-Projection-Kaleidoscope-Spider-Airblown-Inflatable-Halloween-Decoration-THDA5581.html   B076CNN6K5
    607 51409868    B0756DMVSC
    608 51410962    B0756FKLCV
    609 51411020    B0756F3F6J
    610 51411529    B0756FDM74
    611 915505165   B076W25SDZ
    612 400796633   B076VM75ZF
    
    """)
    

    创建 df 并制作副本:

    df = pd.read_table(data, delim_whitespace=True)
    
    df2 = df
    

    将 IDS 转换为数字并使用 na 删除行:

    df2['IDS'] = pd.to_numeric(df2['IDS'], errors="coerce")
    
    df2.dropna(how="any", inplace=True)
    
    print(df2)
    
       Walmart          IDS       ASINS
    0       602   20511489.0  B077BS6737
    1       603   10311487.0  B077BMHVG7
    2       604   10311302.0  B077BRTYCS
    3       605  152381151.0  B077YW9PTQ
    5       607   51409868.0  B0756DMVSC
    6       608   51410962.0  B0756FKLCV
    7       609   51411020.0  B0756F3F6J
    8       610   51411529.0  B0756FDM74
    9       611  915505165.0  B076W25SDZ
    10      612  400796633.0  B076VM75ZF
    

    【讨论】:

    • 我喜欢这个,虽然 pandas 更喜欢用科学记数法或浮点数来表示数据,如你所见,所以我不得不进一步过滤,将其强制为整数。不过效果很好!
    【解决方案3】:

    您可以使用 str.isnumeric() 进行过滤

    walmartIDS = data.loc[data.WalmartIDS.str.isnumeric()]
    walmartIDS
    
        WalmartIDS  ASINS
    602 20511489    B077BS6737
    603 10311487    B077BMHVG7
    604 10311302    B077BRTYCS
    605 152381151   B077YW9PTQ
    607 51409868    B0756DMVSC
    608 51410962    B0756FKLCV
    609 51411020    B0756F3F6J
    610 51411529    B0756FDM74
    611 915505165   B076W25SDZ
    612 400796633   B076VM75ZF
    

    【讨论】:

    • FWIW,她确实提到她不想更改原始数据。
    • @W.Dodge,这只会从数据框中删除非数字行。它不会以任何方式影响原始数据
    • 我知道那部分,但我对 OP 的解释是她想要一个原始数据的 df 和一个处理后数据的 df。
    • 问题内容为:“我不想更改数据框的数据版本,因为它是原始数据。”
    • @W.Dodge 没什么大不了的,只需更改为 df2 = df.loc[df.WalmartIDS.str.isnumeric()]。内存中有 2 个数据帧
    【解决方案4】:

    str.isdigit

    df[df['IDS'].str.isdigit()]
    
        Walmart        IDS       ASINS
    0       602   20511489  B077BS6737
    1       603   10311487  B077BMHVG7
    2       604   10311302  B077BRTYCS
    3       605  152381151  B077YW9PTQ
    5       607   51409868  B0756DMVSC
    6       608   51410962  B0756FKLCV
    7       609   51411020  B0756F3F6J
    8       610   51411529  B0756FDM74
    9       611  915505165  B076W25SDZ
    10      612  400796633  B076VM75ZF
    

    pd.to_numeric + Series.notnull

    df[pd.to_numeric(df['IDS'], errors='coerce').notnull()]
    
        Walmart        IDS       ASINS
    0       602   20511489  B077BS6737
    1       603   10311487  B077BMHVG7
    2       604   10311302  B077BRTYCS
    3       605  152381151  B077YW9PTQ
    5       607   51409868  B0756DMVSC
    6       608   51410962  B0756FKLCV
    7       609   51411020  B0756F3F6J
    8       610   51411529  B0756FDM74
    9       611  915505165  B076W25SDZ
    10      612  400796633  B076VM75ZF
    

    【讨论】:

    • @Vaishali 好问题。我认为浮点数也可以检查...不确定
    【解决方案5】:

    以便您保留原始数据:

    >>> df.join(df.loc[df['IDS'].str.isdigit(), 'IDS'], rsuffix='_clean')
        Walmart IDS ASINS   IDS_clean
    0   602 20511489    B077BS6737  20511489
    1   603 10311487    B077BMHVG7  10311487
    2   604 10311302    B077BRTYCS  10311302
    3   605 152381151   B077YW9PTQ  152381151
    4   606 The-Holiday-Aisle-Projection-Kaleidoscope-Spid...   B076CNN6K5  NaN
    5   607 51409868    B0756DMVSC  51409868
    6   608 51410962    B0756FKLCV  51410962
    7   609 51411020    B0756F3F6J  51411020
    8   610 51411529    B0756FDM74  51411529
    9   611 915505165   B076W25SDZ  915505165
    10  612 400796633   B076VM75ZF  400796633
    

    由有效数字代码组成的列名为IDS_clean。任何文本代码(例如第 4 行)都将包含 NaN 值。

    【讨论】:

      猜你喜欢
      • 2018-06-07
      • 1970-01-01
      • 2013-09-29
      • 1970-01-01
      • 1970-01-01
      • 2018-01-26
      • 2023-03-29
      • 2021-10-24
      • 2020-11-29
      相关资源
      最近更新 更多