【问题标题】:Pandas: Drop NA rows based on shared column valuesPandas:根据共享列值删除 NA 行
【发布时间】:2022-01-21 18:51:36
【问题描述】:

我有以下数据框

import pandas as pd
import numpy as np

df = pd.DataFrame({
    "Country": ["A", "A", "A", "A", "B", "B", "B", "B"],
    "Year": [2020, 2020, 2021, 2021, 2020, 2020, 2021, 2021],
    "Category": [1, 2, 1, 2, 1, 2, 1, 2],
    "Count": [np.nan, np.nan, 1, 2, 3, np.nan, 5, 6]
})

我想删除与CountryYear 列共享值并在Count 列中具有NaN 值的所有值。所以在这种情况下,行 id 0 和 1 将被删除(注意第 5 行不应该被删除)。

这可以通过一些内置的 pandas 函数在不循环的情况下实现吗?

下面的代码达到了预期的效果,但是效率相当低(真实的dataframe要大得多):

for country in df.Country.unique():
    for year in df.Year.unique():
        if df[(df.Country==country) & (df.Year==year)].Count.isna().all(): 
            df.drop(df[(df.Country==country) & (df.Year==year)].index, inplace=True)

有没有更好、更有效的方法?

【问题讨论】:

    标签: python pandas dataframe drop


    【解决方案1】:

    您可以使用groupbyfilter 仅保留“并非每个计数都为空”的组。

    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame({
        "Country": ["A", "A", "A", "A", "B", "B", "B", "B"],
        "Year": [2020, 2020, 2021, 2021, 2020, 2020, 2021, 2021],
        "Category": [1, 2, 1, 2, 1, 2, 1, 2],
        "Count": [np.nan, np.nan, 1, 2, 3, np.nan, 5, 6]
    })
    
    df.groupby(['Country','Year']).filter(lambda x: ~x['Count'].isnull().all())
    

    输出

    Country  Year  Category  Count
    2       A  2021         1    1.0
    3       A  2021         2    2.0
    4       B  2020         1    3.0
    5       B  2020         2    NaN
    6       B  2021         1    5.0
    7       B  2021         2    6.0
    

    【讨论】:

    • 等价于df[df.groupby(["Country", "Year"]).Count.transform("count").ne(0)]
    猜你喜欢
    • 2013-08-12
    • 2017-07-07
    • 1970-01-01
    • 2016-11-01
    • 2020-03-09
    • 1970-01-01
    • 2015-11-14
    • 1970-01-01
    相关资源
    最近更新 更多