根据包含重复项的列比较数据系列列

Compare data series columns based on a column that contains duplicates

我有一个数据集,它是通过在“NAME”列上将 2 个 df 合并在一起创建的,现在我有一个更大的数据集。为了完成 DF,我想对它执行一些逻辑来清理它。

要求: 我想 select 唯一 'NAME' 但我想将名称与最高的销售行相匹配,如果在通过销售列后,所有行都小于 10,则移至呼叫列并且 select highest 具有最高 Call 的行,如果 'CALLS' 中的所有调用都小于 10,则移动到 Target Column select 最高 Target。未对任何行求和。

这是我的 DF:

             NAME       CUSTOMER_SUPPLIER_NUMBER           Sales  Calls  Target
0        OFFICE 1        2222277                             84    170     265
1        OFFICE 1        2222278                             26    103     287
2        OFFICE 1        2222278                             97    167     288
3        OFFICE 2        2222289                              7    167     288
4        OFFICE 2        2222289                              3    130     295
5        OFFICE 2        2222289                              9    195     257
6        OFFICE 3        1111111                              1      2     286
7        OFFICE 3        1111111                              5      2     287
8        OFFICE 3        1111112                              9      7     230
9        OFFICE 4        1111171                             95     193    299
10       OFFICE 5        1111191                              9     193    298

这是我想在最终 DF 中展示的内容:

             NAME       CUSTOMER_SUPPLIER_NUMBER           Sales  Calls  Target
0        OFFICE 1        2222277                             97    167     288
5        OFFICE 2        2222289                              9    195     257
7        OFFICE 3        1111111                              5      2     287
9        OFFICE 4        1111171                             95    193     299
10       OFFICE 5        1111191                              9    193     298

我正在考虑使用 df.itterows()

来解决这个问题

这是我尝试过的方法:

for n, v in df.iterrows(): 
    if int(v['Sales']) > 10:
        calls = df.loc[(v['NAME'] == v) & (int(v['Calls'].max()))]
        if int(calls['Calls']) > 10:
            target =  df.loc[(v['NAME'] == v) & (int(v['Target'].max()))]
        else:
            print("No match found")
    else:
       sales = df.loc[(v['NAME'] == v) & (int(v['Sales'].max())]

但是,我不断收到 KeyError: False 错误消息。对我做错了什么有什么想法吗?

这没有优化,但应该可以满足您的需求。该代码片段将每个 NAME 组发送到 eval_group(),在其中检查每列的最高索引,直到满足销售、呼叫、目标标准。

如果您要进行优化,那么您可以将矢量化或并行原则应用于 eval_group,以便一次针对所有组调用它,而不是依次调用。

一些注意事项,如果发现竞争条件,这将 return 第一行(即在 idxmax() 调用期间多个记录具有相同的最大值)。另外,我相信你的问题,所需答案的第一行应该 OFFICE 1 是第 2 行,而不是第 0 行。

df = pd.read_csv('./data.txt')

def eval_group(df, keys) :
    for key in keys : 
        row_id = df[key].idxmax()
        if df.loc[row_id][key] >= 10 or key == keys[-1] :
            return row_id

row_ids = []
keys = ['Sales','Calls','Target']
for name in df['NAME'].unique().tolist() :
    condition = df['NAME'] == name 
    row_ids.append( eval_group( df[condition], keys) )

df = df[ df.index.isin(row_ids) ]

df
        NAME  CUSTOMER_SUPPLIER_NUMBER  Sales  Calls  Target
2   OFFICE 1                   2222278     97    167     288
5   OFFICE 2                   2222289      9    195     257
7   OFFICE 3                   1111111      5      2     287
9   OFFICE 4                   1111171     95    193     299
10  OFFICE 5                   1111191      9    193     298

这需要几个步骤,您必须在其中构建中间数据帧、执行条件并根据条件结果进行过滤:

temp = (df
        .drop(columns = 'CUSTOMER_SUPPLIER_NUMBER')
        .groupby('NAME', sort = False)
        .idxmax()
         )

# get the booleans for rows less than 10
bools = df.loc(axis=1)['Sales':'Target'].lt(10)

# groupby for each NAME
bools =  bools.groupby(df.NAME, sort = False).all()

# conditions buildup
condlist = [~bool_check.Sales, ~bool_check.Calls, ~bool_check.Target]
choicelist = [temp.Sales, temp.Calls, temp.Target]
# you might have to figure out what to use for default
indices = np.select(condlist, choicelist, default = temp.Sales)

# get matching rows
df.loc[indices]
        NAME  CUSTOMER_SUPPLIER_NUMBER  Sales  Calls  Target
2   OFFICE 1                   2222278     97    167     288
5   OFFICE 2                   2222289      9    195     257
7   OFFICE 3                   1111111      5      2     287
9   OFFICE 4                   1111171     95    193     299
10  OFFICE 5                   1111191      9    193     298