| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 516 人关注过本帖
标题:各位前辈给帮我看看这个代码有什么问题吗?
只看楼主 加入收藏
JHxc
Rank: 2
等 级:论坛游民
帖 子:110
专家分:27
注 册:2019-2-2
结帖率:60%
收藏
已结贴  问题点数:20 回复次数:2 
各位前辈给帮我看看这个代码有什么问题吗?
为什么下面的代码选择规则后,接收规则的变量selected_rules是空的呀!
程序代码:
import pandas as pd
import random
import tkinter as tk
from tkinter import filedialog

root = tk.Tk()
root.withdraw()

# 文件选择框
file_path = filedialog.askopenfilename()
# 读取表格数据
df = pd.read_excel(file_path)

# 定义一个全局变量来保存用户选择的规则
selected_rules = []

# get_input()函数
def get_input():
    x = num_entry.get()
    root.destroy()
    return int(x), selected_rules


# 定义一个函数用于将被勾选的选项保存到一个列表中
def toggle_check(item, var):
    if var.get() == item[1] and item not in selected_rules:
        selected_rules.append(item)
    elif item in selected_rules:
        selected_rules.remove(item)
    update_selected_rules()


# 弹出输入框和单选框,获取输入的数值和选择的规则
root = tk.Tk()

tk.Label(root, text="请输入分配量(600/33=18):").grid(column=0, row=0, sticky='w')
num_entry = tk.Entry(root)
num_entry.grid(column=0, row=1)

tk.Label(root, text="请选择分配规则:").grid(column=0, row=2, sticky='w')

# 增加一个全选复选框
select_all_var = tk.IntVar()
select_all_checkbox = tk.Checkbutton(root, text="全选", variable=select_all_var, anchor='w')
select_all_checkbox.grid(column=0, row=3, sticky='w')

rules = [("按平均数量分配", "quantity", 1), ("按平均金额分配", "amount", 2)]

# 创建一个字典用来保存复选框
checkbox_dict = {}

# 绑定全选复选框的选择事件
def select_all():
    if select_all_var.get():
        for mode in checkbox_dict:
            checkbox_dict[mode].select()
        selected_rules.clear()
        selected_rules.extend(rules)
    else:
        for mode in checkbox_dict:
            checkbox_dict[mode].deselect()
        selected_rules.clear()
    update_selected_rules()

select_all_var.trace_add('write', lambda *args: select_all())

def update_selected_rules():
    global selected_rules
    selected_rules = []
    for item in rules:
        if checkbox_dict[item[1]].cget('selectcolor') == 'white':
            selected_rules.append(item)


rule_var = tk.StringVar()
rule_var.set("quantity")
for i, (text, mode, order) in enumerate(rules):
    # 使用字典保存复选框
    checkbox_dict[mode] = tk.Checkbutton(root, text=text, variable=rule_var,
                                         onvalue=mode, offvalue="", anchor='w',
                                         command=lambda item=(text, mode, order): toggle_check(item, rule_var))
    checkbox_dict[mode].grid(column=0, row=i+4, sticky='w')

button = tk.Button(root, text="确定", command=root.quit)
button.grid(column=0, row=len(rules)+4)

selected_rules = []  # 初始化选中的规则为空列表

root.mainloop()


# 获取输入的数值和选择的规则并使用
num_accounts, selected_rules = get_input()
print(num_accounts, selected_rules)  # 输出输入的数值和选中的规则

# 抽取所有存在的账号名称
existing_accounts = df['账号'].dropna().astype(str)
accounts = existing_accounts.value_counts().index.tolist()

# 根据选择的规则计算每个账号需要分配的id数或金额
num_ids = len(df)
if ("按平均数量分配", "quantity", 1) in selected_rules:
    average_amount = num_ids // num_accounts
    account_distribution = "按平均数量分配"
    print("662")
else:
    total_amount = df['金额'].sum()
    average_amount = total_amount / num_accounts
    account_total_amounts = df.groupby('账号')['金额'].sum().to_dict()
    account_distribution = "按平均金额分配"
    print("66")

    # 根据平均金额计算每个账号需要分配的id数
    num_ids_per_account = {}
    for account, total_amount in account_total_amounts.items():
        num_ids_per_account[account] = int(total_amount / average_amount * num_ids / total_amount)
    total_ids = sum(num_ids_per_account.values())
    if total_ids != num_ids:
        # 调整num_ids_per_account使得总和等于num_ids
        if total_ids > num_ids:
            excess_ids = total_ids - num_ids
            while excess_ids > 0:
                for account in list(num_ids_per_account.keys()):
                    if num_ids_per_account[account] > 0:
                        num_ids_per_account[account] -= 1
                        excess_ids -= 1
                        if excess_ids == 0:
                            break
        else:
            remaining_ids = num_ids - total_ids
            while remaining_ids > 0:
                for account in list(num_ids_per_account.keys()):
                    num_ids_per_account[account] += 1
                    remaining_ids -= 1
                    if remaining_ids == 0:
                        break

# 按金额排序
df_sorted = df.sort_values(by=['金额'])

# 分配账号
assigned_accounts = []
account_id_counts = {}
account_total_amounts = {}

for i in range(num_ids):
    # 如果已分配该账号的id数量达到了上限,则在剩余账号中筛选
    while True:
        if len(accounts) == 0:
            raise ValueError('账号数量不够,请减少分配量或添加更多账号')
        account = random.choice(accounts)
        if selected_rules == "quantity":
            if assigned_accounts.count(account) < num_ids_per_account:
                assigned_accounts.append(account)
                break
        else:
            if account not in account_total_amounts:
                assigned_accounts.append(account)
                account_id_counts[account] = 0
                account_total_amounts[account] = 0
            elif account_total_amounts[account] + df_sorted.loc[df_sorted.index[i], '金额'] > average_amount:
                accounts.remove(account)
                continue
            assigned_accounts.append(account)
        df_sorted.loc[df_sorted.index[i], '账号'] = account

        account_id_counts[account] += 1
        account_total_amounts[account] += df_sorted.loc[df_sorted.index[i], '金额']
        break

        #-----------------------
        # 对于按平均金额分配的规则,重新计算每个账号需要分配的id数
        if selected_rules == "amount":
            num_accounts = len(accounts)
            total_amount = sum(account_total_amounts.values())
            average_amount = total_amount / num_accounts

            # 分配订单
            num_ids_per_account = {}
            total_ids = 0
            for account in accounts:
                num_ids = int(account_total_amounts[account] / average_amount * num_ids / total_amount)
                num_ids_per_account[account] = num_ids
                total_ids += num_ids

            # 调整num_ids_per_account使得总和等于num_ids
            if total_ids != num_ids:
                if total_ids > num_ids:
                    excess_ids = total_ids - num_ids
                    for account in sorted(num_ids_per_account.keys(), key=num_ids_per_account.get, reverse=True):
                        if num_ids_per_account[account] > 0:
                            num_ids_per_account[account] -= 1
                            excess_ids -= 1
                            if excess_ids == 0:
                                break
                else:
                    remaining_ids = num_ids - total_ids
                    for account in sorted(num_ids_per_account.keys(), key=num_ids_per_account.get):
                        num_ids_per_account[account] += 1
                        remaining_ids -= 1
                        if remaining_ids == 0:
                            break

            assigned_amounts = {account: num_ids_per_account[account] * average_amount for account in accounts}

            # 根据应分配金额分配订单
            for account in account_total_amounts:
                assigned_accounts = []
                excess_ids = df_sorted[df_sorted['账号'] == account]

                # 分配其它账号的订单,直到当前账号的订单数量达到应分配数量
                while len(excess_ids) < assigned_amounts[account]:
                    if len(accounts) <= 1:
                        raise ValueError('账号数量不够,请减少分配量或添加更多账号')
                    other_account = random.choice(accounts)
                    if other_account != account:
                        excess_ids_other = df_sorted[df_sorted['账号'] == other_account]
                        excess_ids_to_assign = excess_ids_other.iloc[:assigned_amounts[account] - len(excess_ids)]

                        # 判断是否需要在多个账号之间分配金额
                        if abs(excess_ids_to_assign['金额'].sum() - excess_ids['金额'].sum()) > 2000:
                            diff = excess_ids_to_assign['金额'].sum() - excess_ids['金额'].sum()
                            if diff > 0:
                                excess_ids_to_assign = excess_ids_other.iloc[
                                                       :assigned_amounts[account] - len(excess_ids) + 1]
                                excess_ids_to_assign['账号'] = account
                                excess_ids = pd.concat([excess_ids, excess_ids_to_assign.iloc[:-1]])
                                excess_ids_other.drop(excess_ids_to_assign.iloc[:-1].index, inplace=True)
                            else:
                                excess_ids_to_assign = excess_ids_other.iloc[
                                                       :assigned_amounts[account] - len(excess_ids) - 1]
                                other_account_ids = excess_ids[excess_ids['ID'].str.startswith(other_account)]
                                excess_ids_to_assign.loc[other_account_ids.iloc[0].name, '金额'] += diff
                                excess_ids_to_assign['账号'] = other_account
                                excess_ids = pd.concat([excess_ids, excess_ids_to_assign])
                                excess_ids_other.drop(excess_ids_to_assign.index, inplace=True)
                        else:
                            excess_ids_to_assign['账号'] = account
                            excess_ids = pd.concat([excess_ids, excess_ids_to_assign])
                            excess_ids_other.drop(excess_ids_to_assign.index, inplace=True)

                        assigned_accounts.append(other_account)
                        accounts.remove(other_account)
                        if len(excess_ids) >= assigned_amounts[account]:
                            break

                # 分配当前账号的订单
                excess_ids = excess_ids.sample(frac=1)  # 随机打乱顺序
                excess_ids_to_assign = excess_ids.iloc[:assigned_amounts[account]]
                excess_ids_to_assign['账号'] = account
                excess_ids.drop(excess_ids_to_assign.index, inplace=True)
                account_id_counts[account] += len(excess_ids_to_assign)
                assigned_accounts.append(account)

            # 调整账户之间的总金额
            while True:
                account_total_amounts = {account: df_sorted[df_sorted['账号'] == account]['金额'].sum() for account in
                                         accounts}
                max_amount_account = max(account_total_amounts, key=account_total_amounts.get)
                min_amount_account = min(account_total_amounts, key=account_total_amounts.get)
                diff = account_total_amounts[max_amount_account] - account_total_amounts[min_amount_account]
                if diff < 5000:
                    break
                excess_ids = df_sorted[df_sorted['账号'] == max_amount_account]
                excess_ids_to_assign = excess_ids.sample(n=int(diff / 2))
                excess_ids_to_assign['账号'] = min_amount_account
                excess_ids.drop(excess_ids_to_assign.index, inplace=True)
                account_id_counts[min_amount_account] += len(excess_ids_to_assign)
                if len(excess_ids) == 0:
                    accounts.remove(max_amount_account)
                    continue
                excess_ids = df_sorted[df_sorted['账号'] == min_amount_account]
                excess_ids_to_assign = excess_ids.sample(n=int(diff / 2))
                excess_ids_to_assign['账号'] = max_amount_account
                excess_ids.drop(excess_ids_to_assign.index, inplace=True)
                account_id_counts[max_amount_account] += len(excess_ids_to_assign)

                # 剩余订单随机分配给其他账号
                for i in range(len(excess_ids)):
                    while True:
                        if len(accounts) <= 1:
                            raise ValueError('账号数量不够,请减少分配量或添加更多账号')
                        other_account = random.choice(accounts)
                        if other_account != account and assigned_accounts.count(other_account) < num_ids_per_account[
                            other_account]:
                            excess_ids.loc[excess_ids.index[i], '账号'] = other_account
                            excess_ids.drop(excess_ids.index[i], inplace=True)
                            account_id_counts[other_account] += 1
                            assigned_accounts.append(other_account)
                            accounts.remove(other_account)
                            break

        df_sorted = df_sorted.sort_values(by=['账号', '金额'])

# 输出表格和分配结果
save_path = filedialog.asksaveasfilename(defaultextension=".xlsx")

if save_path:
    df_sorted.to_excel(save_path, index=False)
    print('文件保存成功!')
    print("账号分配结果:")
    for account, count in account_id_counts.items():
        print("{}: {}个id ({:.2f}元)".format(account, count, account_total_amounts.get(account, 0)))
    print(account_distribution)
else:
    print('未选择文件保存路径!')
搜索更多相关主题的帖子: 账号 分配 if for 金额 
2023-06-15 22:04
sheeboard
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:16
帖 子:79
专家分:442
注 册:2023-2-16
收藏
得分:20 
def get_input():
    x = num_entry.get()
    root.destroy()
    return int(x), selected_rules

这个有点疑问,这里selected_rules怎么来的?如果是全局变量,直接操作就是,也不用函数了。

[此贴子已经被作者于2023-6-15 23:57编辑过]

2023-06-15 23:39
JHxc
Rank: 2
等 级:论坛游民
帖 子:110
专家分:27
注 册:2019-2-2
收藏
得分:0 
回复 2楼 sheeboard
selected_rules是通过toggle_check()和update_selected_rules()两个函数来更新的
2023-06-16 00:20
快速回复:各位前辈给帮我看看这个代码有什么问题吗?
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.026200 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved