数据分析与结果呈现
在人群仿真软件AnyLogic中,数据分析与结果呈现是仿真建模的重要环节。通过有效的数据分析和结果呈现,可以更好地理解仿真模型的行为、验证模型的正确性,并为决策提供依据。本节将详细介绍如何在AnyLogic中进行数据收集、分析以及结果的可视化呈现。
数据收集
在AnyLogic中,数据收集可以通过多种方式实现,包括内置的数据收集工具和自定义的数据收集逻辑。以下是一些常用的数据收集方法:
内置数据收集工具
AnyLogic提供了内置的数据收集工具,如statistics和dataset,可以方便地收集仿真过程中产生的数据。
Statistics:
Statistics对象用于收集数值数据的基本统计信息,如平均值、最小值、最大值等。可以用于收集人群数量、等待时间等数据。// 创建一个Statistics对象StatisticspeopleCount=newStatistics();// 在某个事件中更新数据peopleCount.add(people.size());Dataset:
Dataset对象用于收集时间序列数据,可以用于绘制图表。可以用于记录人群数量随时间的变化、各个出口的人流情况等。// 创建一个Dataset对象DatasetpeopleCountOverTime=newDataset();// 在某个事件中更新数据peopleCountOverTime.add(time(),people.size());
自定义数据收集逻辑
对于更复杂的数据收集需求,可以编写自定义的Java代码来实现。例如,记录每个个体的路径选择、停留时间等。
路径选择记录:假设我们需要记录每个个体选择的路径。
// 定义一个ArrayList来存储路径选择ArrayList<String>pathChoices=newArrayList<>();// 在个体离开某个区域时记录路径publicvoidonExitRegion(StringpathName){pathChoices.add(pathName);}停留时间记录:假设我们需要记录每个个体在某个区域的停留时间。
// 定义一个HashMap来存储每个个体的进入时间和停留时间HashMap<Person,Double>entryTimes=newHashMap<>();HashMap<Person,Double>dwellTimes=newHashMap<>();// 在个体进入某个区域时记录进入时间publicvoidonEnterRegion(Personperson){entryTimes.put(person,time());}// 在个体离开某个区域时计算停留时间publicvoidonExitRegion(Personperson){doubleentryTime=entryTimes.get(person);doubledwellTime=time()-entryTime;dwellTimes.put(person,dwellTime);entryTimes.remove(person);}
数据分析
收集到的数据需要进行分析,以提取有用的信息。AnyLogic提供了多种数据处理和分析工具,包括内置的统计函数和自定义的Java代码。
内置统计函数
平均值:计算某个数据集合的平均值。
// 计算人群数量的平均值doubleaveragePeopleCount=peopleCount.getMean();标准差:计算某个数据集合的标准差。
// 计算人群数量的标准差doublestdDevPeopleCount=peopleCount.getStdDev();百分位数:计算某个数据集合的百分位数。
// 计算人群数量的90百分位数doublepercentile90PeopleCount=peopleCount.getPercentile(90);
自定义数据分析
对于更复杂的数据分析需求,可以编写自定义的Java代码。例如,分析路径选择的分布、停留时间的分布等。
路径选择分布:假设我们已经记录了每个个体选择的路径,现在需要分析路径选择的分布。
// 定义一个HashMap来存储路径选择的次数HashMap<String,Integer>pathChoiceCount=newHashMap<>();// 遍历pathChoices,统计每个路径的选择次数for(Stringpath:pathChoices){pathChoiceCount.put(path,pathChoiceCount.getOrDefault(path,0)+1);}// 计算路径选择的分布for(Map.Entry<String,Integer>entry:pathChoiceCount.entrySet()){Stringpath=entry.getKey();intcount=entry.getValue();doublepercentage=(double)count/pathChoices.size()*100;System.out.println(path+": "+percentage+"%");}停留时间分布:假设我们已经记录了每个个体在某个区域的停留时间,现在需要分析停留时间的分布。
// 定义一个ArrayList来存储所有个体的停留时间ArrayList<Double>allDwellTimes=newArrayList<>(dwellTimes.values());// 计算停留时间的基本统计信息doubleaverageDwellTime=allDwellTimes.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);doublemaxDwellTime=allDwellTimes.stream().mapToDouble(Double::doubleValue).max().orElse(0.0);doubleminDwellTime=allDwellTimes.stream().mapToDouble(Double::doubleValue).min().orElse(0.0);// 输出统计信息System.out.println("Average Dwell Time: "+averageDwellTime);System.out.println("Max Dwell Time: "+maxDwellTime);System.out.println("Min Dwell Time: "+minDwellTime);
结果呈现
结果呈现是将分析得到的数据以图表、报告等形式展示出来,以便于理解和决策。AnyLogic提供了多种结果呈现工具,包括内置的图表和自定义的报告。
内置图表
折线图:用于展示时间序列数据的变化。
// 创建一个折线图LineChartpeopleCountChart=newLineChart();// 设置图表的标题和轴标签peopleCountChart.setTitle("People Count Over Time");peopleCountChart.setXLabel("Time (min)");peopleCountChart.setYLabel("People Count");// 添加数据集peopleCountChart.add(peopleCountOverTime);柱状图:用于展示分类数据的频数分布。
// 创建一个柱状图BarChartpathChoiceChart=newBarChart();// 设置图表的标题和轴标签pathChoiceChart.setTitle("Path Choice Distribution");pathChoiceChart.setXLabel("Path");pathChoiceChart.setYLabel("Percentage (%)");// 添加数据for(Map.Entry<String,Integer>entry:pathChoiceCount.entrySet()){Stringpath=entry.getKey();intcount=entry.getValue();doublepercentage=(double)count/pathChoices.size()*100;pathChoiceChart.add(path,percentage);}散点图:用于展示两个变量之间的关系。
// 创建一个散点图ScatterChartdwellTimeScatter=newScatterChart();// 设置图表的标题和轴标签dwellTimeScatter.setTitle("Dwell Time vs. Person ID");dwellTimeScatter.setXLabel("Person ID");dwellTimeScatter.setYLabel("Dwell Time (min)");// 添加数据for(Map.Entry<Person,Double>entry:dwellTimes.entrySet()){Personperson=entry.getKey();doubledwellTime=entry.getValue();dwellTimeScatter.add(person.getId(),dwellTime);}
自定义报告
对于更复杂的结果呈现需求,可以编写自定义的Java代码来生成报告。例如,生成一个HTML报告,展示关键的仿真结果和统计信息。
生成HTML报告:假设我们需要生成一个包含人群数量、路径选择分布和停留时间分布的HTML报告。
// 创建一个StringBuilder来构建HTML报告StringBuilderreportBuilder=newStringBuilder();// 添加报告标题reportBuilder.append("<html><head><title>Simulation Report</title></head><body>");reportBuilder.append("<h1>Simulation Report</h1>");// 添加人群数量的统计信息reportBuilder.append("<h2>People Count Statistics</h2>");reportBuilder.append("<p>Average People Count: "+averagePeopleCount+"</p>");reportBuilder.append("<p>Max People Count: "+maxPeopleCount+"</p>");reportBuilder.append("<p>Min People Count: "+minPeopleCount+"</p>");// 添加路径选择的分布reportBuilder.append("<h2>Path Choice Distribution</h2>");reportBuilder.append("<table>");reportBuilder.append("<tr><th>Path</th><th>Percentage (%)</th></tr>");for(Map.Entry<String,Integer>entry:pathChoiceCount.entrySet()){Stringpath=entry.getKey();intcount=entry.getValue();doublepercentage=(double)count/pathChoices.size()*100;reportBuilder.append("<tr><td>"+path+"</td><td>"+percentage+"%</td></tr>");}reportBuilder.append("</table>");// 添加停留时间的分布reportBuilder.append("<h2>Dwell Time Distribution</h2>");reportBuilder.append("<p>Average Dwell Time: "+averageDwellTime+" min</p>");reportBuilder.append("<p>Max Dwell Time: "+maxDwellTime+" min</p>");reportBuilder.append("<p>Min Dwell Time: "+minDwellTime+" min</p>");// 结束HTML报告reportBuilder.append("</body></html>");// 将报告写入文件try{Files.write(Paths.get("simulation_report.html"),reportBuilder.toString().getBytes());}catch(IOExceptione){e.printStackTrace();}
实例分析
为了更好地理解数据收集、分析和结果呈现的过程,我们通过一个具体的实例来展示如何在一个停车场仿真模型中实现这些功能。
停车场仿真模型概述
假设我们正在开发一个停车场仿真模型,模型中包含多个入口、出口和停车位。我们需要收集以下数据:
每个入口的车辆进入数量
每个出口的车辆离开数量
每个停车位的占用时间和占用次数
车辆在停车场内的平均停留时间
数据收集
首先,我们需要在仿真模型中定义数据收集对象。
// 定义数据收集对象StatisticsentryCounts=newStatistics();StatisticsexitCounts=newStatistics();StatisticsparkingOccupancyTime=newStatistics();HashMap<Integer,Integer>parkingOccupancyCount=newHashMap<>();在模型的事件中更新数据收集对象。
// 在车辆进入停车场时记录进入数量publicvoidonVehicleEnter(intentryId){entryCounts.add(1);}// 在车辆离开停车场时记录离开数量publicvoidonVehicleExit(intexitId){exitCounts.add(1);}// 在车辆占用停车位时记录占用时间和占用次数publicvoidonVehiclePark(intparkingId,doublestartTime){// 记录开始占用时间parkingOccupancyTime.add(startTime);// 记录占用次数parkingOccupancyCount.put(parkingId,parkingOccupancyCount.getOrDefault(parkingId,0)+1);}// 在车辆离开停车位时更新占用时间publicvoidonVehicleLeave(intparkingId,doubleendTime){doublestartTime=parkingOccupancyTime.getLastValue();doubleoccupancyTime=endTime-startTime;parkingOccupancyTime.add(occupancyTime);}数据分析
在仿真结束时,计算并输出相关的统计信息。
// 计算入口和出口的统计信息doubleaverageEntryCount=entryCounts.getMean();doubleaverageExitCount=exitCounts.getMean();// 计算停车位的占用时间和占用次数doubleaverageParkingOccupancyTime=parkingOccupancyTime.getMean();HashMap<Integer,Double>parkingOccupancyTimeDistribution=newHashMap<>();for(intparkingId:parkingOccupancyCount.keySet()){intcount=parkingOccupancyCount.get(parkingId);doublepercentage=(double)count/parkingOccupancyCount.values().stream().mapToInt(Integer::intValue).sum()*100;parkingOccupancyTimeDistribution.put(parkingId,percentage);}// 计算车辆在停车场内的平均停留时间doubleaverageDwellTime=parkingOccupancyTime.getMean();结果呈现
最后,使用内置图表和自定义报告来呈现分析结果。
// 创建入口和出口的折线图LineChartentryExitChart=newLineChart();entryExitChart.setTitle("Entry and Exit Counts Over Time");entryExitChart.setXLabel("Time (min)");entryExitChart.setYLabel("Count");entryExitChart.add("Entry Counts",entryCounts);entryExitChart.add("Exit Counts",exitCounts);// 创建停车位占用次数的柱状图BarChartparkingOccupancyChart=newBarChart();parkingOccupancyChart.setTitle("Parking Occupancy Distribution");parkingOccupancyChart.setXLabel("Parking ID");parkingOccupancyChart.setYLabel("Percentage (%)");for(Map.Entry<Integer,Double>entry:parkingOccupancyTimeDistribution.entrySet()){intparkingId=entry.getKey();doublepercentage=entry.getValue();parkingOccupancyChart.add(String.valueOf(parkingId),percentage);}// 创建平均停留时间的散点图ScatterChartaverageDwellTimeChart=newScatterChart();averageDwellTimeChart.setTitle("Average Dwell Time vs. Parking ID");averageDwellTimeChart.setXLabel("Parking ID");averageDwellTimeChart.setYLabel("Dwell Time (min)");for(intparkingId:parkingOccupancyCount.keySet()){doubledwellTime=parkingOccupancyTime.getLastValue();averageDwellTimeChart.add(parkingId,dwellTime);}// 生成HTML报告StringBuilderreportBuilder=newStringBuilder();reportBuilder.append("<html><head><title>Parking Simulation Report</title></head><body>");reportBuilder.append("<h1>Parking Simulation Report</h1>");// 添加入口和出口的统计信息reportBuilder.append("<h2>Entry and Exit Counts</h2>");reportBuilder.append("<p>Average Entry Count: "+averageEntryCount+"</p>");reportBuilder.append("<p>Average Exit Count: "+averageExitCount+"</p>");// 添加停车位的统计信息reportBuilder.append("<h2>Parking Occupancy Statistics</h2>");reportBuilder.append("<p>Average Occupancy Time: "+averageParkingOccupancyTime+" min</p>");reportBuilder.append("<table>");reportBuilder.append("<tr><th>Parking ID</th><th>Percentage (%)</th></tr>");for(Map.Entry<Integer,Double>entry:parkingOccupancyTimeDistribution.entrySet()){intparkingId=entry.getKey();doublepercentage=entry.getValue();reportBuilder.append("<tr><td>"+parkingId+"</td><td>"+percentage+"%</td></tr>");}reportBuilder.append("</table>");// 添加车辆的平均停留时间reportBuilder.append("<h2>Average Dwell Time</h2>");reportBuilder.append("<p>Average Dwell Time: "+averageDwellTime+" min</p>");// 结束HTML报告reportBuilder.append("</body></html>");// 将报告写入文件try{Files.write(Paths.get("parking_simulation_report.html"),reportBuilder.toString().getBytes());}catch(IOExceptione){e.printStackTrace();}通过以上步骤,我们可以在AnyLogic中实现数据收集、分析和结果呈现。这些工具和方法可以帮助我们更好地理解仿真模型的行为,验证模型的正确性,并为决策提供依据。希望这些内容对您在人群仿真软件二次开发中有所帮助。