# approach 2: deviation is analyzed for time between the registration points # time between two stations and time between arrival and departure module betweenRegistrationPoints include("./output.jl") using Statistics, CSV, Dates, DataFrames using .output export getDifferences function getDifferences(modPerfData, settings) df1, perfDataDirection1, df2, perfDataDirection2 = prepareData(modPerfData, settings) plotData1 = calculateDeviation(df1, perfDataDirection1, settings) plotData2 = calculateDeviation(df2, perfDataDirection2, settings) return plotData1, plotData2 end """ Function is preparing the data if necesary and calling another function to prepare DataFrames to save the results of the following analyses. """ function prepareData(modPerfData, settings) # determine current line and its station list if settings.objectInFocus == "single line" lineNr = 1 else lineNr = findall(x -> x == settings.analyzedLine, settings.allLines) lineNr = lineNr[1] end stationList1 = settings.stationLists[lineNr] stationList2 = reverse(stationList1) df1 = createDataFrame(stationList1, settings) df2 = createDataFrame(stationList2, settings) select!(modPerfData, Not(:rownumber)) modPerfData = filter(row -> row[:ZUGEREIGNIS_DS100] in stationList1, modPerfData) modPerfData[!, :rownumber] = axes(modPerfData, 1) df = modPerfData[modPerfData[:, :rownumber].!=0, :] # the station data of TSS has to be changed (somtimes wrong order) if stationList1[1] == "TSS" || stationList2[1] == "TSS" for row in eachrow(modPerfData) if row.rownumber > 1 && row.ZUGEREIGNIS_DS100 == "TSS" if modPerfData.ZUGEREIGNIS_DS100[row.rownumber-1] == "TSS" && ( modPerfData.ZUGEREIGNIS_TYP[row.rownumber-1] == 10 || modPerfData.ZUGEREIGNIS_TYP[row.rownumber-1] == 50 ) row1 = modPerfData[row.rownumber-1, :] row2 = modPerfData[row.rownumber, :] df[row.rownumber, :] = row1 df[row.rownumber-1, :] = row2 end end end end perfDataDirection1 = df[df[:, :ZUGEREIGNIS_RICHTUNG].==stationList2[1], :] perfDataDirection2 = df[df[:, :ZUGEREIGNIS_RICHTUNG].==stationList1[1], :] return df1, perfDataDirection1, df2, perfDataDirection2 end function createDataFrame(stationList, settings) df = DataFrame() point1 = Any[] point2 = Any[] counter = 0 if settings.objectInFocus != "Stuttgarter Stammstrecke" if stationList[1] == "TSS" pushfirst!(stationList, stationList[1]) counter = convert(Int, (length(stationList) - 1) / 2) sequence = repeat(["station", "section"], counter) elseif stationList[size(stationList, 1)] == "TSS" push!(stationList, stationList[size(stationList, 1)]) counter = convert(Int, (length(stationList) - 1) / 2) sequence = repeat(["section", "station"], counter) else counter = convert(Int, (length(stationList) - 1) / 2 + 0.5) sequence = repeat(["section", "station"], counter) pop!(sequence) end else push!(stationList, stationList[length(stationList)]) pushfirst!(stationList, stationList[1]) counter = convert(Int, (length(stationList) - 1) / 2 + 0.5) sequence = repeat(["station", "section"], counter) pop!(sequence) end #create station list for differences for i = 2:length(stationList) push!(point1, stationList[i-1]) push!(point2, stationList[i]) end df[!, :point1] = point1 df[!, :point2] = point2 df[!, :sequence] = sequence return df end """ Function is calculating the deviation for each section and stop. Selected quantiles are being created. """ function calculateDeviation(df1, perfData, settings) deviationArray = Any[] perfData[!, :row] = axes(perfData, 1) for row in eachrow(df1) deviationSequence = Any[] for rowData in eachrow(perfData) if rowData.row != 1 && perfData.ZUGEREIGNIS_DS100[rowData.row-1] == row.point1 && rowData.ZUGEREIGNIS_DS100 == row.point2 if ( rowData.ZUGEREIGNIS_TYP == 10 || rowData.ZUGEREIGNIS_TYP == 40 ) && ( perfData.ZUGEREIGNIS_TYP[rowData.row-1] == 20 || perfData.ZUGEREIGNIS_TYP[rowData.row-1] == 50 ) actual = Second( convert( Dates.Second, Dates.DateTime( perfData.ZUGEREIGNIS_ISTZEIT[rowData.row], "dd.mm.yyyy HH:MM", ) - Dates.DateTime( perfData.ZUGEREIGNIS_ISTZEIT[rowData.row-1], "dd.mm.yyyy HH:MM", ), ), ) estimated = Second( convert( Dates.Second, Dates.DateTime( perfData.ZUGEREIGNIS_SOLLZEIT[rowData.row], "dd.mm.yyyy HH:MM", ) - Dates.DateTime( perfData.ZUGEREIGNIS_SOLLZEIT[rowData.row-1], "dd.mm.yyyy HH:MM", ), ), ) deviation = Dates.value(actual - estimated) push!(deviationSequence, deviation) elseif ( rowData.ZUGEREIGNIS_TYP == 20 || rowData.ZUGEREIGNIS_TYP == 50 ) && ( perfData.ZUGEREIGNIS_TYP[rowData.row-1] == 10 || perfData.ZUGEREIGNIS_TYP[rowData.row-1] == 40 ) actual = Second( convert( Dates.Second, Dates.DateTime( perfData.ZUGEREIGNIS_ISTZEIT[rowData.row], "dd.mm.yyyy HH:MM", ) - Dates.DateTime( perfData.ZUGEREIGNIS_ISTZEIT[rowData.row-1], "dd.mm.yyyy HH:MM", ), ), ) estimated = Second( convert( Dates.Second, Dates.DateTime( perfData.ZUGEREIGNIS_SOLLZEIT[rowData.row], "dd.mm.yyyy HH:MM", ) - Dates.DateTime( perfData.ZUGEREIGNIS_SOLLZEIT[rowData.row-1], "dd.mm.yyyy HH:MM", ), ), ) deviation = Dates.value(actual - estimated) push!(deviationSequence, deviation) end end end if length(deviationSequence) == 0 deviationSequence = [10] row.sequence = "noData" end push!(deviationArray, deviationSequence) end quantile = "" quantile = settings.quantile[1] quantArray = Any[] average = Any[] meridian = Float64[] for row in deviationArray x = quantile!(row, parse(Float64, quantile) / 100) y = mean(row) z = median(row) push!(quantArray, x) push!(average, y) push!(meridian, z) end nameColumn = "deviation_" * quantile df1[!, nameColumn] = quantArray df1[!, :averageDeviation] = average df1[!, :median] = meridian points = String[] for row in eachrow(df1) if row.point1 != row.point2 push!(points, row.point1 * "-" * row.point2) else push!(points, row.point1) end end select!(df1, Not(:point1)) df1[!, :points] = points df1 = df1[df1[:, :sequence].!="noData", :] return df1 end end