在数据帧中查找邻居

2024-05-17 21:39:13 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个自行车数据集,在那里我有商店的专栏,它们在哪里出售,以及一些关于自行车型号的信息我需要比较每家商店的型号销售数字。因此,我需要执行以下操作:

  • 按商店对自行车进行分组:

    groups = df.groupby('store_id')

  • 然后,对于该商店中的每个模型,我需要找到具有相似特征的模型。这是相似的高度、长度、重量等。为此,我设置了10%的差异界限,这意味着如果两个模型之间的重量差异小于10%,则另一个模型是可比较的邻居

  • 最后,对于每一款车型,我想看看它在竞争对手中的排名,如果它的表现优于50%的竞争对手,那么它就会被贴上“畅销书”的标签

问题是,我不知道如何执行步骤2和步骤3。有人有主意吗?我已经在pandas文档中查看了Groupby.Transform,但我不知道它如何适合整个图片

非常感谢你的帮助


Tags: 数据模型信息df自行车步骤数字差异
1条回答
网友
1楼 · 发布于 2024-05-17 21:39:13

试试这个:

import pandas as pd
import numpy as np


def sales_rank(x, df):
    df_ns = df.set_index('id')
    df_ns = df_ns.loc[x.neighbors, 'sales']
    df_ns.sort_values(ascending=False, inplace=True)
    df_ns = df_ns.reset_index()
    return df_ns[df_ns.id == x.id].index[0]


df = pd.DataFrame(data={'id': range(5), 'weight': [20, 21, 23, 43, 22], 'sales':[200, 100, 140, 100, 100]})
df['neighbors'] = df.weight.apply(lambda x: df.id[np.isclose(df.weight.values, x, rtol=0.10)].values)
df['sales_rank_in_neighborhood'] = df.apply(lambda x: sales_rank(x, df) , axis=1)
df['top_seller'] = df.apply(lambda x: x.sales_rank_in_neighborhood < len(x.neighbors)//2, axis=1)
print(df)

输出

   id  weight  sales     neighbors  sales_rank_in_neighborhood  top_seller
0   0      20    200     [0, 1, 4]                           0        True
1   1      21    100  [0, 1, 2, 4]                           3       False
2   2      23    140     [1, 2, 4]                           0        True
3   3      43    100           [3]                           0       False
4   4      22    100  [0, 1, 2, 4]                           2       False

请注意,在单元素社区中没有畅销书。调整规则以适合您的目的

我希望这有帮助

编辑

我添加了一个针对组的解决方案、定义邻里关系的多个规则和固定销售排名实施:

import pandas as pd
import numpy as np


def ns(x, df):
    weight_rule = np.isclose(df.weight.values, x.weight, rtol=0.10)
    gear_rule = df.gear == x.gear
    type_rule = df.type == x.type
    return df.id[np.logical_and.reduce((weight_rule, gear_rule, type_rule))].values


def sales_rank(x, df):
    df_ns = df.set_index('id')
    df_ns = df_ns.loc[x.neighbors, 'sales']
    df_ns.sort_values(ascending=False, inplace=True)
    df_ns = df_ns.reset_index()
    return df_ns[df_ns.id == x.id].index[0]


df = pd.DataFrame(data={'store_id': [0, 1, 0, 1, 0], 'id': range(5), 'weight': [20, 21, 23, 43, 22], 'gear': [3, 3, 3, 7, 3], 'type':['mountain', 'mountain', 'mountain', 'bmx', 'mountain'], 'sales':[200, 100, 140, 100, 100]})
# Columns for results
df['neighbors'] = ''
df['sales_rank_in_neighborhood'] = ''
df['top_seller'] = ''
groups = df.groupby('store_id')

for _, g in groups:
    df_temp = df.loc[g.index, :]
    df_temp.neighbors = df_temp.apply(lambda x: ns(x, df_temp), axis=1)
    df_temp.sales_rank_in_neighborhood = df_temp.apply(lambda x: sales_rank(x, df_temp), axis=1)
    df_temp.top_seller = df_temp.apply(lambda x: x.sales_rank_in_neighborhood < len(x.neighbors)//2, axis=1)
    df.loc[g.index, :] = df_temp

print(df)

输出

   store_id  id  weight  gear      type  sales  neighbors sales_rank_in_neighborhood top_seller
0         0   0      20     3  mountain    200     [0, 4]                          0       True
1         1   1      21     3  mountain    100        [1]                          0      False
2         0   2      23     3  mountain    140     [2, 4]                          0       True
3         1   3      43     7       bmx    100        [3]                          0      False
4         0   4      22     3  mountain    100  [0, 2, 4]                          2      False

我想有一种方法可以避免分组循环,但这似乎奏效了

相关问题 更多 >