问题1:对于64w条评教数据,我们如何对其进行可信度分析
一. 数据清洗
处理前的数据(部分)
第一轮清洗源码
package CleanData;
import Data01.AllComment;
import java.util.ArrayList;
import java.util.HashSet;
/**
* description: CleanData.FirstClean
*
* 第一轮清洗:
* 对数据进行初步粗处理
*
* 剔除的数据特征:总评数据重复
*
* 第一次第一轮清洗 5.21 21:42
* 1. 对于总评重复评价的(count >= 3)情况一律删除(但由于某些同学的评教数据特殊性,未删除全面,疑似有遗漏)
* 第二次第一轮清洗 5.22 10:40
* 2. 每一位同学(11/12条数据)中,成功只保留了一条或两条总评数据(初步清洗成功!)
*
* 清洗后的结果:
* 1. 存在子项交错分布的情况(13579,2468)
* 2. 存在标注(实验课和理论课)错误【放到最后一轮清洗完成】
* 3. 存在子项重复(总评重复)
* 4. 存在子项重复(总评不重复)
*
* 第二轮清洗的预期效果:
* 1. 解决子项内容交错分布的情况【解决方案:可能由于特殊学生的评价内容造成的算法问题】
* 2. 对于上述的情况3和4,记录下studentId - teacherId,并且删除有关该信息的所有评教条目
* 3. 对于上述情况2的标注问题,放到最后一轮解决【问题暂存】
*
* date: 2021/5/21 18:44 <br>
* author: 闫济丞 <br>
* version: 1.0 <br>
*/
public class FirstClean {
//我对老师的总体评价 常量
final String COUNT01 = "总体评价";
//最后一个子项 常量
final String COUNT02 = "总的来说";
//每一个评论内容的关键字
final String COUNT1 = "系统性";
final String COUNT2 = "挑战性";
final String COUNT3 = "指导有方";
final String COUNT4 = "有帮助的反馈";
final String COUNT5 = "教学资源";
final String COUNT6 = "教学设计";
final String COUNT7 = "解决实际问题";
final String COUNT8 = "启发性";
final String COUNT9 = "考核";
final String COUNT10 = "总的来说";
//做标记(记录出现的重复数量)
int stringCount = 0;
//用于记录老师-学生的无效数据(重复评价的数据)
ArrayList<String> shouldDeleteDataInfo = new ArrayList<>();
/**
* 区分理论课还是实验课
* @param allInfo 所有数据(删除后的数据)
*/
public ArrayList<AllComment> firstClean(ArrayList<AllComment> allInfo) {
for (AllComment data : allInfo) {
if (data.getCommentName().contains(COUNT01)) {
// System.out.println("count++执行 ----------------此时count = " + stringCount);
stringCount++; //出现次数+1
}
if (data.getCommentName().contains(COUNT02)) {
// System.out.println("count清空执行 ----------------此时count = " + stringCount);
stringCount = 0; //出现次数统计变量清空为0
}
if (stringCount == 2 && !data.getCommentName().contains(COUNT1) && !data.getCommentName().contains(COUNT2)
&& !data.getCommentName().contains(COUNT3) && !data.getCommentName().contains(COUNT4)
&& !data.getCommentName().contains(COUNT5) && !data.getCommentName().contains(COUNT6)
&& !data.getCommentName().contains(COUNT7) && !data.getCommentName().contains(COUNT8)
&& !data.getCommentName().contains(COUNT9) && !data.getCommentName().contains(COUNT10)) {
// System.out.println("修改标注!!!!!");
data.setCommentName("我对老师的总体评价(实验课)");
}
}
return allInfo;
}
/**
* 正式删除(不修改标注)的方法
* @param allInfo 所有数据
* @return 返回处理后的数据
*/
public ArrayList<AllComment> delMethod(ArrayList<AllComment> allInfo) {
for (AllComment data : allInfo) {
if (data.getCommentName().contains(COUNT01)) {
// System.out.println("count++执行 ----------------此时count = " + stringCount);
stringCount++; //出现次数+1
}
if (data.getCommentName().contains(COUNT02)) {
// System.out.println("count清空执行 ----------------此时count = " + stringCount);
stringCount = 0; //出现次数统计变量清空为0
}
if (stringCount >= 3) shouldDeleteDataInfo.add(data.getTeacherId() + "-" + data.getStudentId());
//[上一行表示]:如果出现的次数比三大,那么需要记录当前学生的编号和老师编号
}
//21:21测试
//验证集合中的个数
// System.out.println("21:22测试-------需要删除的条数为 = " + shouldDeleteDataInfo.size());
//去重测试
shouldDeleteDataInfo = new ArrayList(new HashSet(shouldDeleteDataInfo)); //去重成功!20:00
// System.out.println("21:22测试-------集合中的内容为:");
// for (String str : shouldDeleteDataInfo) {
// System.out.println(str);
// }
//测试要删除的学生id和教师id
for (String str : shouldDeleteDataInfo) {
String[] strArr = str.split("-");
// System.out.println("teacherID = " + strArr[0] + ", studentID = " + strArr[1]);
// delMethod1(strArr[0], strArr[1], allInfo);
for (int i=0; i< allInfo.size(); i++) {
if (allInfo.get(i).getTeacherId().equals(strArr[0]) && allInfo.get(i).getStudentId().equals(strArr[1])) {
allInfo.remove(i);i--;
}
}
// System.out.println("teacherID = " + strArr[0] + ", studentID = " + strArr[1] + "-----------成功删除!");
}
return allInfo;
}
}
第二轮清洗源码
package CleanData;
import Data01.*;
import java.util.ArrayList;
import java.util.HashSet;
/**
* description: CleanData.SecondClean <br>
*
* 第二轮清洗:
*
* 实现效果:
*
* 1. 剔除了:子项重复,总评重复
* 2. 剔除了:子项不重复,总评重复
*
* date: 2021/5/22 11:19 <br>
* author: 闫济丞 <br>
* version: 1.0 <br>
*/
public class SecondClean {
String teacherId;
String studentId;
int count = 0; //记录子项出现的次数
ArrayList<String> wantDelData = new ArrayList<>();
/**
* 第二轮清洗主要实现
* @param allData 所有数据
* @return 处理后的所有数据
*/
public ArrayList<AllComment> second(ArrayList<AllComment> allData) {
for (AllComment data : allData) {
count++;
// System.out.println("----- 没有经过判断的count = " + count);
// System.out.println("data = " + data);
if (data.getCommentName().contains("总的来说")) {
//与12和11比较
if (count == 12 || count == 11) {
count = 0;
} else {
//记录
// System.out.println("应该记录下来" + data.getTeacherId());
teacherId = data.getTeacherId();
studentId = data.getStudentId();
wantDelData.add(teacherId + "-" + studentId);
count = 0;
}
}
// System.out.println("+++++ 判断以后的count = " + count + "\n");
}
//去重
wantDelData = new ArrayList<>(new HashSet<>(wantDelData));
// //输出测试
// for (String data : wantDelData) {
// System.out.println(data);
// }
System.out.println("共有数据量:" + wantDelData.size());
//-----------------------开始正式删除-----------------------
//测试要删除的学生id和教师id
for (String str : wantDelData) {
String[] strArr = str.split("-");
// System.out.println("teacherID = " + strArr[0] + ", studentID = " + strArr[1]);
// delMethod1(strArr[0], strArr[1], allInfo);
for (int i=0; i< allData.size(); i++) {
if (allData.get(i).getTeacherId().equals(strArr[0]) && allData.get(i).getStudentId().equals(strArr[1])) {
allData.remove(i);i--;
}
}
// System.out.println("teacherID = " + strArr[0] + ", studentID = " + strArr[1] + "-----------成功删除!");
}
return allData;
}
}
手动清洗代码
package CleanData;
import Data01.AllComment;
import java.util.ArrayList;
/**
* description: Manual <br>
* date: 2021/5/22 13:51 <br>
* author: 闫济丞 <br>
* version: 1.0 <br>
*/
public class ManualDel {
public ArrayList<AllComment> manualDel(ArrayList<AllComment> allData) {
//第一次手动删除
//s:10132
/*
Data.Comment02{commentName='课程内容具有一定的挑战性,我要努力学习才能达到课程要求', teacherId='4778', studentId='10132', score=75}
Data.Comment04{commentName='老师关注我们的平时的学习,对我的问题(包括作业、考核等)给予及时有帮助的反馈', teacherId='4778', studentId='10132', score=75}
Data.Comment06{commentName='老师通过课堂教学设计,鼓励我独立思考和积极参与课堂讨论,激发了我的学习兴趣和积极性', teacherId='4778', studentId='10132', score=75}
Data.Comment08{commentName='我觉得老师知识渊博,讲课清晰有条理,重点、难点突出,富有启发性', teacherId='4778', studentId='10132', score=75}
Data.Comment10{commentName='总的来说,我认为这门课程会对我今后的学习、工作、生活有很大帮助', teacherId='4778', studentId='10132', score=75}
*/
for (int i=0; i<allData.size(); i++) {
if ((allData.get(i).getStudentId().equals("10132"))) {
// System.out.println("找到10132的学生");
// System.out.println(allData.get(i));
allData.remove(i);i--;
}
}
//第二次手动删除
//s:12233
/*
Data.Comment01{commentName='课程安排具有很好的系统性和逻辑性,我能循序渐进地深入学习', teacherId='5350', studentId='12233', score=95}
Data.Comment03{commentName='老师的课程教学组织的很好,指导有方', teacherId='5350', studentId='12233', score=95}
Data.Comment05{commentName='老师提供的教学资源(教材、参考书、网络资源等),对我学习帮助很大', teacherId='5350', studentId='12233', score=95}
Data.Comment07{commentName='通过这门课程的学习,我理解并掌握了课程重要的基础知识,形成了较完整的知识体系,能运用所学的知识和思维方式解决实际问题', teacherId='5350', studentId='12233', score=95}
Data.Comment09{commentName='我知道这门课程考核的构成,我的努力和学习成果能体现在成绩中', teacherId='5350', studentId='12233', score=95}
Data.SumComment01{commentName='我对老师教学的总体评价(理论课)', teacherId='5356', studentId='12233', score=95}
Data.Comment01{commentName='课程安排具有很好的系统性和逻辑性,我能循序渐进地深入学习', teacherId='5356', studentId='12233', score=95}
Data.Comment02{commentName='课程内容具有一定的挑战性,我要努力学习才能达到课程要求', teacherId='5356', studentId='12233', score=95}
Data.Comment03{commentName='老师的课程教学组织的很好,指导有方', teacherId='5356', studentId='12233', score=95}
Data.Comment04{commentName='老师关注我们的平时的学习,对我的问题(包括作业、考核等)给予及时有帮助的反馈', teacherId='5356', studentId='12233', score=95}
Data.Comment05{commentName='老师提供的教学资源(教材、参考书、网络资源等),对我学习帮助很大', teacherId='5356', studentId='12233', score=95}
Data.Comment06{commentName='老师通过课堂教学设计,鼓励我独立思考和积极参与课堂讨论,激发了我的学习兴趣和积极性', teacherId='5356', studentId='12233', score=95}
Data.Comment07{commentName='通过这门课程的学习,我理解并掌握了课程重要的基础知识,形成了较完整的知识体系,能运用所学的知识和思维方式解决实际问题', teacherId='5356', studentId='12233', score=95}
Data.Comment08{commentName='我觉得老师知识渊博,讲课清晰有条理,重点、难点突出,富有启发性', teacherId='5356', studentId='12233', score=95}
Data.Comment09{commentName='我知道这门课程考核的构成,我的努力和学习成果能体现在成绩中', teacherId='5356', studentId='12233', score=95}
Data.Comment10{commentName='总的来说,我认为这门课程会对我今后的学习、工作、生活有很大帮助', teacherId='5356', studentId='12233', score=95}
*/
for (int i=0; i<allData.size(); i++) {
if ((allData.get(i).getStudentId().equals("12233"))) {
// System.out.println("找到10132的学生");
// System.out.println(allData.get(i));
allData.remove(i);i--;
}
}
return allData;
}
}
第三轮清洗源码
package CleanData;
import Data01.*;
import java.util.ArrayList;
import java.util.HashSet;
/**
* description: CleanData.ThirdClean <br>
*
* 第三轮清洗数据
*
* 删除重复(总评)评价的数据
* 【总评重复视为无效数据(冗余数据)】
*
* 例如:
* Data.SumComment01{commentName='我对老师教学的总体评价(理论课)', teacherId='4307', studentId='12525', score=95}
* Data.SumComment01{commentName='我对老师教学的总体评价(理论课)', teacherId='4307', studentId='12525', score=95}
* Data.SumComment01{commentName='我对老师教学的总体评价(理论课)', teacherId='4960', studentId='12525', score=85}
* Data.SumComment01{commentName='我对老师教学的总体评价(理论课)', teacherId='4962', studentId='12525', score=75}
* Data.SumComment01{commentName='我对老师教学的总体评价(理论课)', teacherId='4461', studentId='12787', score=85}
* Data.SumComment01{commentName='我对老师教学的总体评价(理论课)', teacherId='5584', studentId='12787', score=95}
* Data.SumComment01{commentName='我对老师教学的总体评价(理论课)', teacherId='6756', studentId='12787', score=75}
*
* date: 2021/5/22 17:20 <br>
* author: 闫济丞 <br>
* version: 1.0 <br>
*/
public class ThirdClean {
ArrayList<String> recordSonCommentsTeacherIdArr;
public ArrayList<AllComment> thirdClean(ArrayList<AllComment> allData) {
recordSonCommentsTeacherIdArr = recordSonCommentsTwoId(allData);
// System.out.println("测试所有教师id为");
// for (String id : recordSonCommentsTeacherIdArr) {
// System.out.println(id);
// }
// System.out.println("教师数量为" + recordSonCommentsTeacherIdArr.size()); //613名教师
//开始处理
for (int i=0; i<allData.size(); i++) {
if ((allData.get(i) instanceof SumComment01) &&
!recordSonCommentsTeacherIdArr.contains(allData.get(i).getTeacherId()+allData.get(i).getStudentId())) {
//如果总评中的教师id不在 recordSonCommentsTeacherIdArr 集合中,则删除该条总评数据
allData.remove(i); i--;
}
}
return allData;
}
/**
* 记录子项评价中 教师的id和学生id,保存到集合中并返回
* @param allData 所有信息数据
* @return 存有所有教师id学生id的集合
*/
private ArrayList<String> recordSonCommentsTwoId(ArrayList<AllComment> allData) {
ArrayList<String> recordSonCommentsTeacherIdArr = new ArrayList<>();
for (int i = 0; i < allData.size(); i++) {
if (!(allData.get(i) instanceof SumComment01) && !(allData.get(i) instanceof SumComment02)) {
//如果这个数据属于子项评价数据
recordSonCommentsTeacherIdArr.add(allData.get(i).getTeacherId() + allData.get(i).getStudentId());
}
}
//去重操作
recordSonCommentsTeacherIdArr = new ArrayList<>(new HashSet<>(recordSonCommentsTeacherIdArr));
return recordSonCommentsTeacherIdArr;
}
}
调用清洗模块
package RunProgram;
import CleanData.FirstClean;
import CleanData.ManualDel;
import CleanData.SecondClean;
import CleanData.ThirdClean;
import Data01.AllComment;
import Data01.ReadData;
import Data01.WriteData;
import java.io.IOException;
import java.util.ArrayList;
/**
* description: RunProgram.Main <br>
* date: 2021/5/21 16:23 <br>
* author: 闫济丞 <br>
* version: 1.0 <br>
*/
public class Que01 {
public static void main(String[] args) {
ArrayList<AllComment> allData = new ReadData().readData();
//计算总耗时
Long time1 = System.currentTimeMillis();
// System.out.println("主方法中的数据量为:" + allData.size());
System.out.println("写入成功!");
//----------------------------------------第一轮清洗----------------------------------
//先删除
//测试要删除的教师id和学生id
System.out.println(">【控制台提示信息】开始进行第一轮清洗!");
Long t1 = System.currentTimeMillis();
System.out.println("正在清洗.....");
allData = new FirstClean().delMethod(allData);
System.out.println(">【控制台提示信息】第一轮清洗完毕!");
Long t2 = System.currentTimeMillis();
System.out.println("------------> 耗时:" + (t2-t1) / 1000 + "秒");
// //再区分理论课和实验课
// allData = new CleanData.FirstClean().firstClean(allData);
//----------------------------------------第二轮清洗----------------------------------
System.out.println(">【控制台提示信息】开始进行第二轮清洗!");
t1 = System.currentTimeMillis();
System.out.println("正在清洗.....");
allData = new SecondClean().second(allData);
System.out.println(">【控制台提示信息】第二轮清洗完毕!");
t2 = System.currentTimeMillis();
System.out.println("------------>耗时:" + (t2-t1) / 1000 + "秒");
//----------------------------------------手动删除------------------------------------
System.out.println(">【控制台提示信息】开始进行手动清洗!");
t1 = System.currentTimeMillis();
System.out.println("正在清洗.....");
allData = new ManualDel().manualDel(allData);
System.out.println(">【控制台提示信息】手动清洗数据完毕!");
t2 = System.currentTimeMillis();
System.out.println("------------>耗时:" + (t2-t1) / 1000 + "秒");
//----------------------------------------第三轮清洗----------------------------------
System.out.println(">【控制台提示信息】开始进行第三轮清洗!");
t1 = System.currentTimeMillis();
System.out.println("正在清洗.....");
allData = new ThirdClean().thirdClean(allData);
System.out.println(">【控制台提示信息】第三轮清洗完毕!");
t2 = System.currentTimeMillis();
System.out.println("------------>耗时:" + (t2-t1) / 1000 + "秒");
//-----------------------------------------修改标注----------------------------------
System.out.println(">【控制台提示信息】开始修改标注!");
t1 = System.currentTimeMillis();
System.out.println("正在修改.....");
allData = new FirstClean().firstClean(allData);
System.out.println(">【控制台提示信息】修改完毕!");
t2 = System.currentTimeMillis();
System.out.println("------------>耗时:" + (t2-t1) / 1000 + "秒");
//----------------------------------------序列化实现备份-------------------------------
System.out.println(">【控制台提示信息】开始进行序列化对象实现备份!");
t1 = System.currentTimeMillis();
System.out.println("正在备份.....");
try {
ReadResult.saveInfo(allData, "allData");
} catch (IOException e) {
e.printStackTrace();
}
System.out.println(">【控制台提示信息】序列化成功!");
t2 = System.currentTimeMillis();
System.out.println("------------>耗时:" + (t2-t1) / 1000 + "秒");
//开始写入txt文件
System.out.println(">【控制台提示信息】开始写入txt文件");
t1 = System.currentTimeMillis();
System.out.println("正在写入.....");
for (AllComment data : allData) {
// System.out.println(data);
//开始写入txt文件
new WriteData().writeData(data);
}
System.out.println(">【控制台提示信息】写入成功!");
t2 = System.currentTimeMillis();
System.out.println("------------>耗时:" + (t2-t1) / 1000 + "秒");
Long time2 = System.currentTimeMillis();
System.out.println("============================================================");
System.out.println("总耗时 " + (time2-time1)/1000 + "秒");
}
}
读取数据
package Data01;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
/**
* description: Data.ReadData <br>
* date: 2021/5/21 16:20 <br>
* author: 闫济丞 <br>
* version: 1.0 <br>
*/
public class ReadData {
//用于存储每一条信息
ArrayList<AllComment> allInfo = new ArrayList<>();
public ArrayList<AllComment> readData() {
//数据条数
int dataCount = 1;
try {
BufferedReader br = new BufferedReader(new FileReader("src/allData.txt"));
//若读取data1的数据,则会输出正确的学生人数
//若读取allData的数据,则可以正确的将数据进行分离
String line = null;
while ((line = br.readLine()) != null) {
// System.out.println(line);
/*
line代表每一行数据的信息
*/
// System.out.print(dataCount + "> ");
input(line);
dataCount++;
}
//关闭最外层流即可
br.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
//展示信息条数
System.out.println("【控制台信息】共有" + (dataCount-1) + "条数据");
return allInfo;
}
public void input(String line) {
//记录当前所获取的学生学号,以便于区分不同学生的信息
String tempStuNum = line.substring(5, 10);
//开始存入
//拆分line 拆分为四个部分
//定义临时数组用于存储这四个部分
String[] tempStr = line.split(" ");
for (int i = 0; i < tempStr.length; i++) {
//分析:tempStr[0] 教师id
// tempStr[1] 学生id
// tempStr[2] 评价内容
// tempStr[3] 得分
// System.out.print(tempStr[i] + " "); //用于测试是否划分正确 【5.20 19:01测试成功】
}
// System.out.println();
//此时tempStr数组成功存储了一行信息
if (tempStr[2].contains("系统性和逻辑性")) {
Comment01 comment01 = new Comment01(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(comment01);
} else if (tempStr[2].contains("挑战性")) {
Comment02 comment02 = new Comment02(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(comment02);
} else if (tempStr[2].contains("教学组织的很好")) {
Comment03 comment03 = new Comment03(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(comment03);
} else if (tempStr[2].contains("(包括作业、考核等)")) {
Comment04 comment04 = new Comment04(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(comment04);
} else if (tempStr[2].contains("教材、参考书、网络资源等")) {
Comment05 comment05 = new Comment05(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(comment05);
} else if (tempStr[2].contains("激发了我的学习兴趣和积极性")) {
Comment06 comment06 = new Comment06(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(comment06);
} else if (tempStr[2].contains("通过这门课程的学习")) {
Comment07 comment07 = new Comment07(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(comment07);
} else if (tempStr[2].contains("我觉得老师知识渊博")) {
Comment08 comment08 = new Comment08(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(comment08);
} else if (tempStr[2].contains("我知道这门课程考核的构成")) {
Comment09 comment09 = new Comment09(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(comment09);
} else if (tempStr[2].contains("总的来说")) {
Comment10 comment10 = new Comment10(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(comment10);
} else if (tempStr[2].contains("我对老师教学的总体评价")) {
SumComment01 sumComment01 = new SumComment01(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(sumComment01);
} else if (tempStr[2].contains("我对老师教学的总体评价")) {
SumComment02 sumComment02 = new SumComment02(tempStr[0], tempStr[1], Integer.parseInt(tempStr[3]));
allInfo.add(sumComment02);
}
//存储完毕
//验证集合中的数据
// System.out.println("此时集合中有数据量为 = " + allInfo.size());
}
}
写入数据
package Data01;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
/**
* description: Data.WriteData <br>
* date: 2021/5/21 18:17 <br>
* author: 闫济丞 <br>
* version: 1.0 <br>
*/
public class WriteData {
public void writeData(AllComment oneLineData) {
try {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("src/writeDataTXT.txt", true));
bufferedWriter.write(oneLineData.toString());
bufferedWriter.newLine();
bufferedWriter.flush();
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public void writeDataToExcel(AllComment oneLineData) {
try {
BufferedWriter bufferedWriter = new BufferedWriter(new FileWriter("src/toExcel.txt", true));
bufferedWriter.write(oneLineData.getTeacherId()+" "+oneLineData.getStudentId()+
" "+oneLineData.getCommentName()+" "+oneLineData.getScore());
bufferedWriter.newLine();
bufferedWriter.flush();
bufferedWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
处理后的数据(部分)
【数据清洗模块说明完毕】2021/5/25 11:02