各位,学校要求某几天内全员常态化核酸全院学生完成,现在要求每天平均抽取每个班的学生(学生不能连号),例如学号2011951xx
班级44人,要求4天内采集完则抽取班级内几个同学(如不够除尽量平均),则按学号应该抽取11位,尽量在01~44内分开
现有表格中有数据 :学号,班级 ,姓名。总计600名学生。
要求输出excel为各个天的核酸人员。
如何用代码完成这些要求呢(工作之用,实属无奈,求解决)
假设这是你的表格
如果你要四次分完,就在旁边输入1,2,3,4。五次就1,2,3,4,5;以此类推。
选中这几个格。按住Ctrl键,并点击选中区的右下角的角点往下拖
拖完后的效果是这样的
然后从上到下选中所有的内容区域
排序后,c列是1的就是第一天的学生,2的就是第二天的……
目前功能:
1、自定义筛选天数,比如查看某一天所有班级的所有学生
2、自定义筛选班级,比如查看某一天单个班级的所有学生
3、除了4天,可以根据自己需求定义其他的天数比如5天或者6天。
使用步骤:
1、运行以下代码,输入文件为'demo.csv',输出文件为'output.csv'
2、ctrl + t设置为超级表,然后选择最后一列为'1'即可查看第一天的,选择'2'即为第二天的,'3'为第三天的,'4'为第四天的
同时可以在第一行班级选择来筛选班级。
demo.csv和output.csv我发附件给你。
day = 4
input_file = 'demo.csv'
output_file = 'output.csv'
class_dict = {}
with open(input_file, "r") as fr:
lines = fr.readlines()
first_line = None
for index, line in enumerate(lines):
if index == 0:
first_line = line
continue
item = line.replace('\n', '').split(',')
_id = item[0]
study_id = item[1]
class_name = item[2]
student_name = item[3]
if class_name not in class_dict.keys():
class_dict[class_name] = {}
index -= 1
number = index % 4 + 1
class_dict[class_name][study_id] = {
'student_name': student_name,
'day_number': number
}
# print("class_dict", class_dict)
with open(output_file, "w") as fw:
fw.write(first_line.replace('\n', ',天数\n'))
index = 0
for class_name, class_item in class_dict.items():
index += 1
# 序号,学号,班级,姓名, 天数
for study_id in class_item.keys():
student_name = class_item[study_id]['student_name']
day_number = class_item[study_id]['day_number']
new_line = '{_id},{study_id},{class_name},{student_name},{day_number}\n'.format(_id=index, study_id=study_id, class_name=class_name, student_name=student_name,day_number=day_number)
fw.write(new_line)
python的读写表格就不需要给了吧,xlwt随便查下就有教程。
主要是说一下如何平均抽取:
1、把所有人读取到一个dict;
2、总共600名,4天检完,平均每天需要抽取600/4;
3、看看总共几个班级,每班每天需要抽取600/4/班级数;
4、使用python自带random,开始挑人数,挑够了就从全集里把这个人剔除,从剩下的人里继续random
如果需要代码,那就再联系。
先写个思路:
只要提取学号和班级就可以了,因为学号是唯一的,而每个班级人数可能不一样,比如一班20人,二班30人,如果要两天做完核酸的话,一班每天做10人,二班每天做15人。
所以,
题主确认一下是这个思路不?
random 获取随机数,然后再把需要的数据在python内进行读取拼接,输出,完事。
每个学生一个编号,例如46个学生,就是1-46个编号,每个编号对应一个学生,取random取编号(平均几次,一个班就取几次)
不太懂你的意思,是随机产生学号吗?
import random
day = 3
num = []
for i in range(int(44 / day)):
num.append(random.randint(1,44))
num = sorted(num)
for j in num:
print("2011951{}".format(j))
就分层抽就可以了。你发我excel ,我测试一下
这个要看你是每天每个班采集一部分人,再从这一部分人中抽取几位,4天共抽11人
还是4天采集完后统一每个班抽取11人。
import math
import random
# pip install openpyxl
import openpyxl
# Excel表结构
# A列 B列 C列 D列
# 班级 学号 姓名 第几天
# A 201195101 name_101 3
# A 201195102 name_102 3
# A 201195103 name_103 1
# A 201195104 name_104 1
# A 201195105 name_105 4
# A 201195106 name_106 4
# A 201195107 name_107 2
# 未能通过实现让每天检测的人员实现不连号的情况,这应只是概率问题,相信一直循环验证是可以实现的
# 本机10000次以内未能出现不连号的情况。
class Student(object):
"""docstring for Student"""
def __init__(self, exl_name):
super(Student, self).__init__()
self.exl_name = exl_name
self.wb = self.get_wb()
self.sheet = self.wb.active
self.stu_info = self.get_stu_info()
def get_wb(self):
# 加载Excel表
wb = openpyxl.load_workbook(filename=self.exl_name)
return wb
def get_stu_info(self):
# 获取数据
stu_info = dict()
for row in self.sheet.iter_rows(min_row=2,max_col=3):
class_name = row[0].value
stu_number = row[1].value
stu_name = row[2].value
if class_name not in stu_info:
stu_info[class_name] = list()
dic = {"name":stu_name,"number":stu_number}
stu_info[class_name].append(dic)
# print(stu_info)
return stu_info
def avg_count(self,class_name,days):
# 获得每班平均每天人数
stus = self.stu_info[class_name]
avg_count = math.ceil(len(stus)/days)
return avg_count
def avg_stu(self,class_name,days):
# 按每天每班人数 抽取学号 如果不连号是否能够实现?既然是随机抽取那么连号和不连号的意义是什么?
choice_data = dict()
stus = self.stu_info[class_name]
stu_numbers = [stu["number"] for stu in stus]
avg_count = self.avg_count(class_name,days)
for day in range(1,days+1):
choice_data[day] = list()
if len(stu_numbers)>=avg_count:
for count in range(1,avg_count+1):
stu_num = random.choice(stu_numbers)
choice_data[day].append(stu_num)
stu_numbers.remove(stu_num)
else:
choice_data[day].extend(stu_numbers)
# print(choice_data)
return choice_data
def check_nums(self,everyday_stus,days):
# 检查当天检测学号是否连号
# 既然是随机抽取 那么连号和不连号就是概率问题了 没有测出能出现不连号的情况
# 判断连号不连号的情况 本机测试一直没有通过
for day in range(1,days+1):
stus = everyday_stus[day]
stus.sort()
# print(day,stus)
for index in range(1,len(stus)):
if stus[index]-stus[index-1] == 1:
print(day,stus[index],stus[index-1])
return False
return True
def run(self):
# 获取班级名称
class_names = list(self.stu_info.keys())
# 所需总天数
days = 4
# days = int(input("输入天数:"))
everyday_stus = dict()
# 循环获取数据校验是否存在连号
while 1:
for class_name in class_names:
choice_data = self.avg_stu(class_name,days)
for day in range(1,days+1):
if day not in everyday_stus:
everyday_stus[day] = list()
everyday_stus[day].extend(choice_data[day])
print("over")
self.write_exl(everyday_stus)
return
# 如果需要校验学号是否连号 去掉return开始校验
if self.check_nums(everyday_stus,days) is True:
print("over")
self.write_exl(everyday_stus)
return
# self.check_nums(everyday_stus)
def write_exl(self,everyday_stus):
# 写入Excel
for key,val in everyday_stus.items():
for number in val:
for row in self.sheet.iter_rows(min_row=2,min_col=2,max_col=4):
stu_num = row[0].value
if number == stu_num:
row[-1].value=key
# 保存
self.wb.save("student_over.xlsx")
if __name__=="__main__":
stu = Student(exl_name="student.xlsx")
stu.run()
如果真实纯工作需要,还是用表格处理吧,楼上有给出表格处理的方案,简单效率
把现有表格给我,可以调试实现你的功能。
贴主不适合编程,连python也能拼写错误