大熊猫根据组的记录数有条件地删除记录

时间:2019-11-24 11:26:40

标签: python-3.x pandas pandas-groupby

我有一个像这样的数据框

import pandas as pd
import numpy as np

raw_data = {'Country':['UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK','UK'],
    'Product':['A','A','A','A','B','B','B','B','B','B','B','B','C','C','C','D','D','D','D','D','D'],
            'Week': [1,2,3,4,1,2,3,4,5,6,7,8,1,2,3,1,2,3,4,5,6], 
       'val': [5,4,3,1,5,6,7,8,9,10,11,12,5,5,5,5,6,7,8,9,10]
    }

df2 = pd.DataFrame(raw_data, columns = ['Country','Product','Week', 'val'])

print(df2)

enter image description here

和映射数据框

mapping = pd.DataFrame({'Product':['A','C'],'Product1':['B','D']}, columns = ['Product','Product1'])

enter image description here

,我想根据映射比较产品。产品A数据应与产品B数据匹配。逻辑是产品A的记录数为4,因此产品B的记录也应为4,而这4个记录应来自产品A的上周号之前和之后的周号,以及包括上周的数字。因此,在第4周的第1周之前,即第3周,以及在第4周的第2周即5,6和第4周数据之后。

类似地,产品C的记录数为3,因此产品D的记录也应为3,并且那些记录在产品C的上周之前和之后的记录也是如此。因此,产品c的上周为3,因此产品D的记录将为周数2,3。 ,4。

想要的数据框如下所示,我想删除那些黄色记录

enter image description here

2 个答案:

答案 0 :(得分:1)

为以下产品定义以下功能,从 df 中选择行 映射中的当前

def selRows(row, df):
    rows_1 = df[df.Product == row.Product]
    nr_1 = rows_1.index.size
    lastWk_1 = rows_1.Week.iat[-1]
    rows_2 = df[df.Product.eq(row.Product1) & df.Week.ge(lastWk_1 - 1)].iloc[:nr_1]
    return pd.concat([rows_1, rows_2])

然后按以下方式称呼它:

result = pd.concat([ selRows(row, grp)
    for _, grp in df2.groupby(['Country'])
        for _, row in mapping.iterrows() ])

上面的列表理解在DataFrames上创建一个列表-的结果 selRows 的调用:

  • 来自 df2 的每组行,用于连续的国家(外部循环),
  • 映射(内部循环)中的每一行。

然后 concat 将它们全部合并为一个DataFrame。

答案 1 :(得分:0)

解决方案首先通过react-native bundle --entry-file index.js --platform ios --dev false --bundle-output ios/main.jsbundle --assets-dest ios/assets DataFrame创建映射列,并通过mappingCountry按组创建用于映射长度和最后(最大值)值的字典:

Product

然后将Series.map个dict值过滤掉较少的值,然后使用DataFrame.head按第二个字典按长度过滤:

df2['mapp'] = df2['Product'].map(mapping.set_index('Product1')['Product'])
df1 = df2.groupby(['Country','Product'])['Week'].agg(['max','size'])

#subtracted 1 for last previous value
dprev = df1['max'].sub(1).to_dict()
dlen = df1['size'].to_dict()
print(dlen)
{('UK', 'A'): 4, ('UK', 'B'): 8, ('UK', 'C'): 3, ('UK', 'D'): 6}

然后过滤不匹配的df3 = (df2[df2[['Country','mapp']].apply(tuple, 1).map(dprev) <= df2['Week']] .groupby(['Country','mapp']) .apply(lambda x: x.head(dlen.get(x.name)))) print(df3) Country Product Week val mapp Country mapp UK A 6 UK B 3 7 A 7 UK B 4 8 A 8 UK B 5 9 A 9 UK B 6 10 A C 16 UK D 2 6 C 17 UK D 3 7 C 18 UK D 4 8 C 原始行,添加新的mapping['Product1']并进行排序:

df3