我有不同的商家、产品和人气排名,大小参差不齐。
我想统计每个商家的累计匹配产品数量,然后返回调整后的排名(即累计+1)。但我只想计算第一组匹配产品,并且仅当它们从 1 开始时,如果总数不 > 2,则调整后的排名重置为 1。
在此示例中,匹配模式为 apple|banana|orange
理想的输出是一个包含商家、排名和调整后排名的数据框:
在 this post 的帮助下,我已经成功解决了这个问题。但我感觉我所做的事情效率很低。有没有更好的方法来实现这一点?
df = pd.read_csv('data.csv')
pattern = 'apple|banana|orange'
# Check column contains substring and create bool column
df['Match'] = np.where(df['Product'].str.contains(pattern), True, False)
# perform count on True values, resetting when False
df['Count'] = df.groupby(df['Match'].astype(int).diff().ne(0).cumsum())['Match'].cumsum()
# filter out False values
filtered = df[df['Match'] != False]
# filter out values where rank != count, as these aren't in the 1st grouping
filtered = filtered.loc[filtered['Rank'] == filtered['Count']]
# get max rank from remaining values
filtered = filtered.groupby('Merchant')['Count'].max().reset_index(name='Adjusted Rank')
# add 1 to ranks to get maximum position, reset ranking to 1 if there aren't 2 concurrent values
filtered['Adjusted Rank'] = np.where(filtered['Adjusted Rank'] > 2, (filtered['Adjusted Rank'] + 1), 1)
# merge dfs, drop columns, drop dupes
df = df.merge(filtered, how='left', on='Merchant').fillna(1)
df = df[['Merchant','Rank','Adjusted Rank']]
df.drop_duplicates('Merchant', inplace=True)
感谢您的帮助!
最佳答案
您可以使用:
products = ['apple', 'banana', 'orange']
out = (df
.groupby('Merchant', as_index=False)
.agg(**{'Adjusted Rank': ('Product', lambda s: s.isin(products).cummin().sum()+1)})
)
输出:
Merchant Adjusted Rank
0 Merchant 1 3
1 Merchant 2 4
2 Merchant 3 1
如果调整后的排名 <= 2,则排名为 1:
out['Rank'] = out['Adjusted Rank'].where(out['Adjusted Rank'].gt(2), 1)
关于python - 根据 Pandas 中的多个条件和 groupby 执行列内匹配值的累积计数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74721482/