【问题标题】:Pandas: delete or change specific rows according to multiple columns valuesPandas:根据多列值删除或更改特定行
【发布时间】:2019-05-23 11:43:30
【问题描述】:

我有一个元组到值列表之间的字典,例如:

{
    ('book1', 'US'): [1, 5],
    ('book2', 'CA'): [3]
}

元组表示 pandas DataFrame 中的列值(也可能有其他列),列表表示同一数据框中单个列中的值。
假设我的数据框看起来像这样:

    book country  value
0  book1      US      1
1  book1      US      9
2  book1      US      5
3  book2      MX      7
4  book2      CA      3
5  book1      CA      1

我想删除上面dict 表示的行或将这些行的值更改为0。
所以结果将是:

    book country  value
0  book1      US      0
1  book1      US      9
2  book1      US      0
3  book2      MX      7
4  book2      CA      0
5  book1      CA      1

或者:

    book country  value
0  book1      US      9
1  book2      MX      7
2  book1      CA      1

这样做的最佳方法是什么?
我想在一个相当大的数据帧上执行此操作,它应该尽可能高效。

我的想法是做这样的事情,但它似乎不是很有效(由于多个loc)并且我得到重复行而不是删除行。 (我不想使用drop_duplicates,因为一开始可能有我不想删除的重复项)

data_frame.set_index(['book', 'country'], inplace=True)
for key, values in rows_to_remove.iteritems():
    data_frame.loc[key] = data_frame.loc[key][~data_frame.loc[key]['value'].isin(values)]
data_frame.reset_index(inplace=True)

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    您可以通过Index.isinboolean indexing 创建元组列表并检查成员资格:

    d = {
        ('book1', 'US'): [1, 5],
        ('book2', 'CA'): [3]
    }
    
    tups = [k + (x, ) for k, v in d.items() for x in v]
    
    df = df[~df.set_index(['book','country','value']).index.isin(tups)]
    print (df)
        book country  value
    1  book1      US      9
    3  book2      MX      7
    5  book1      CA      1
    

    对于按条件设置0,使用loc

    df.loc[df.set_index(['book','country','value']).index.isin(tups), 'value'] = 0
    print (df)
        book country  value
    0  book1      US      0
    1  book1      US      9
    2  book1      US      0
    3  book2      MX      7
    4  book2      CA      0
    5  book1      CA      1
    

    另一种解决方案:

    tups = [k + (x, ) for k, v in d.items() for x in v]
    
    df1 = pd.DataFrame(tups, columns=['book','country','value'])
    
    df2 = pd.concat([df, df1, df1], ignore_index=True)
    df = df2[~df2.duplicated(keep=False)]
    print (df)
        book country  value
    1  book1      US      9
    3  book2      MX      7
    5  book1      CA      1
    

    【讨论】:

    • 不错! set_index 贵吗?如果我有多个指标维度并且我想在每个指标上运行多次怎么办? (即如果我有value1value2value3)。为简单起见,我没有将其添加到问题中,但是您认为在这种情况下您建议的方法仍然是最好的方法吗?谢谢!
    • @A.Sarid - 我想不,应该有更贵的isin
    • @A.Sarid - 添加了另一个解决方案,你能检查一下吗?
    • 谢谢!解决方案当然有效。你能解释一下有什么区别吗?是不是更有效率?假设我有多个值列并且我需要在每个列上运行此逻辑,我仍在试图弄清楚这是否是最有效的方法。
    • 其实原来的df可能有重复,所以你建议的新解决方案对我不好。但是其他的效果很好,效率不是很高,但是效果很好。
    猜你喜欢
    • 1970-01-01
    • 2021-02-27
    • 1970-01-01
    • 2018-04-28
    • 2016-11-01
    • 1970-01-01
    • 2013-08-12
    • 1970-01-01
    • 2017-07-07
    相关资源
    最近更新 更多