通过多重嵌套键对数据进行分组

Grouping data by multiply nested keys

我有一些输入数据:

data = [('15.05.2022 12:36', 46879, 'Clinton Bill', '555-55-55', 'USA, White House', 'Cond', 'id_1', '56', 10),
        ('15.05.2022 12:36', 46879, 'Clinton Bill', '555-55-55', 'USA, White House', 'Cond', 'id_1', '56', 1),
        ('15.05.2022 12:36', 46879, 'Clinton Bill', '555-55-55', 'USA, White House', 'Lub', 'id_2', '45', 5),
        ('15.05.2022 13:00', 33990, 'Monika L.', '666-66-66', 'USA, Pennsylvania Av', 'Cond', 'id_1', '56', 7),
        ('15.05.2022 13:00', 33990, 'Monika L.', '666-66-66', 'USA, Pennsylvania Av', 'Lub', 'id_2', '45', 3),
        ('15.05.2022 13:00', 33990, 'Monika L.', '666-66-66', 'USA, Pennsylvania Av', 'Lub', 'id_2', '45', 9)]

行项目是:

(日期, user_id, user_name, user_phone, user_address, product_name, product_id, product_price, product_count)

我应该按 user_id 对数据进行分组,以表示有关每个 UNIQUE 用户的信息,其中 相同产品的数量将被计算在内,使用 python 3 脚本。

像这样:

output_data = [('15.05.2022 12:36', 46879, 'Clinton Bill', '555-55-55', 'USA, white house', ('Con', 'id_1', '56', 11), ('Lub','id_2', '45', 5)),
               ('15.05.2022 13:00', 33990, 'Monika L.', '666-66-66', 'Colorado', ('Con', 'id_1', '56', 7), ('Lub', 'id_2', '45', 12))]

或者您可能会建议一些执行输出数据的更好方法。我将通过机器人将其发送给管理员。

我认为您可以按唯一 ID 对数据进行分组,然后计算乘积总和。基于此输出,您可以轻松创建结构。

import collections
output_data = dict()

for date, user_id, user_name, user_phone, user_address, product_name, product_id, product_price, product_count in data:
    if not output_data.get(user_id):
        output_data[user_id] = collections.defaultdict(int)
    output_data[user_id][product_id] += product_count

print(output_data)

Pandas 风格:

# convert your data to dataframe
df = pd.DataFrame(data, columns=columns)
columns_minus_one = list(df.columns[:-1])

df2 = df.groupby(columns_minus_one , as_index=False).sum('product_count')

输出:

然后你可以得到返回列表:

df2.values.tolist()

您可以使用 itertools.groupby and operator.itemgetter 两次(第一次是按客户分组,第二次是按产品分组)以获得所需的输出。这是代码。

import itertools
import operator

def my_groupby(lst, by_keys, return_keys):
    getter = operator.itemgetter(*by_keys)
    returner = operator.itemgetter(*return_keys)

    # If the data is not sorted, sort it by by_keys to make the groupby work properly
    sorted_data = sorted(lst, key=getter)
    it = itertools.groupby(sorted_data, key=getter)
    for key, subiter in it:
        # Yield the key as list and desired columns from the data
        yield list(key), [returner(item) for item in subiter]

res = my_groupby(data, by_keys=range(5), return_keys=range(5, 9))
output_data =[]

for customer in res:
    prod = list(my_groupby(customer[1], by_keys=range(3), return_keys=[3]))
    prod_total = list(map(lambda x: (*x[0], sum(x[1])), prod))
    output_data.append(customer[0] + prod_total)

print(output_data)

输出:

[['15.05.2022 12:36', 46879, 'Clinton Bill', '555-55-55', 'USA, White House', ('Cond', 'id_1', '56', 11), ('Lub', 'id_2', '45', 5)]
['15.05.2022 13:00', 33990, 'Monika L.', '666-66-66', 'USA, Pennsylvania Av', ('Cond', 'id_1', '56', 7), ('Lub', 'id_2', '45', 12)]]

变量 res 包含按客户详细信息(列号 0 到 5)以及产品详细信息分组的数据。

下一个循环是按产品详细信息分组。 prod 将包含产品详细信息和产品数量。使用 map 函数计算总产品计数。计算结果附加在一个空列表中,output_data 以获得所需的输出。