Построение гистограммы с наложением графика нормальности смещено - PullRequest
1 голос
/ 06 января 2020

То, что я пытаюсь сделать, это иметь график нормальности или «кривую колокола», как некоторые могут сказать, поверх гистограммы. Я использовал код для создания своей гистограммы и другой код для получения данных о нормальности, которые показаны ниже. На данный момент все, что я хочу знать, - это как объединить созданную мною гистограмму, используя код, и график гладких линий рассеяния XY (график нормальности), созданный вручную путем создания диаграммы с использованием данных нормальности, которые я получаю из кода.

Я попытался объединить их вместе, чтобы это выглядело так: enter image description here

И, как вы можете видеть, график нормальности не совсем совпадает с гистограммой , Я обнаружил, что это из-за разницы в оси, которая вызывает его смещение. Мои данные о нормальности взяты из всех данных, а гистограмма использует значения счетчиков. Однако, когда я нахожу среднее значение и стандартное отклонение значений счетчика и изменяю данные в соответствии с ним, это происходит

enter image description here

При этом даже более смещен.

Код для гистограммы.

Sub MakeHistogram()

    Dim src_sheet As Worksheet, Graph_sheet As Worksheet
    Dim selected_range As Range
    Dim r As Integer, firstOne As Integer
    Dim percent_cell As Range
    Dim num_percent As Integer
    Dim count_range As Range, bin_range As Range
    Dim new_chart As Chart
    Dim lRow As Long
    Dim RngToCover As Range, Chtob As ChartObject
    Dim Snum As Long, Bnum As Long

    With Application
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
        .EnableEvents = False
        .DisplayStatusBar = False
    End With

    With Sheets("Data")
        lRow = .Cells(.Rows.Count, 1).End(xlUp).Row
        Set selected_range = .Range(.Cells(2, 1), .Cells(lRow, 1))
    End With
    Set src_sheet = Sheets("Data")
    Set Graph_sheet = Sheets("Graphs")

    num_percent = selected_range.Count

    ' See how many bins we will have.
    Const BIN_SIZE As Integer = 5
    Dim num_bins As Integer
    num_bins = 150 \ BIN_SIZE

    ' Make the bin separators.
    Graph_sheet.Cells(1, 2) = "Bins"

    For r = 1 To num_bins - 1
        Graph_sheet.Cells(r + 2, 2) = r * BIN_SIZE
    Next r

    Graph_sheet.Cells(r + 2, 2) = 150
    ' Make the counts.
    Graph_sheet.Cells(1, 1) = "Counts"
    Set count_range = Graph_sheet.Range("A" & 3 & ":A" & num_bins + 2)
    Set bin_range = Graph_sheet.Range("B" & 3 & ":B" & num_bins + 2)

    count_range = WorksheetFunction.Frequency(selected_range, bin_range)

    ' Make the range labels.

    Graph_sheet.Cells(1, 3) = "Ranges"
    For r = 1 To num_bins
    firstOne = 1
    If r = 1 Then firstOne = 0
        Graph_sheet.Cells(r + 2, 3) = "'" & _
            (5 * (r - 1)) + firstOne & "-" & _
              5 * (r - 1) + 5
        Graph_sheet.Cells(r + 2, 3).HorizontalAlignment = _
            xlRight
    Next r
    r = num_bins

    Graph_sheet.Cells(r + 1, 3).HorizontalAlignment = xlRight

    ' Make the chart.
    Set new_chart = Charts.Add()
    With new_chart
        .ChartType = xlColumnClustered
        .SetSourceData Source:=Graph_sheet.Range("A" & 3 & ":A" & _
            num_bins + 2), _
            PlotBy:=xlColumns
        .Location where:=xlLocationAsObject, _
            Name:="Graphs"
    End With

    'Get the largest and smallest number
    Bnum = WorksheetFunction.Max(selected_range.Value)
    Snum = WorksheetFunction.Min(selected_range.Value)

    With Graph_sheet
        Set RngToCover = .Range(.Cells(6, 5), .Cells(23, 11))
    End With

    With ActiveChart

        With .ChartArea.Format
            ' White background
            .Fill.ForeColor.RGB = RGB(255, 255, 255)

            ' Red border
            With .Line
                .ForeColor.RGB = RGB(100, 100, 100)
                .Weight = 2
            End With
        End With

        .HasTitle = True
        .ChartTitle.Characters.Text = title & " Histogram"
        With .Axes(xlCategory, xlPrimary)
            .HasTitle = True
            .AxisTitle.Characters.Text = xStr
        End With
        .Axes(xlValue, xlPrimary).HasTitle = True
        .Axes(xlValue, xlPrimary).AxisTitle.Characters.Text = "Count"

        ' Display percentage ranges on the X axis.
        .SeriesCollection(1).XValues = "='" & _
            "Graphs" & "'!R" & 3 & "C3:R" & _
            num_bins + 2 & "C3"

        Set Chtob = .Parent
        Chtob.Height = RngToCover.Height
        Chtob.Width = RngToCover.Width
        Chtob.Top = RngToCover.Top
        Chtob.Left = RngToCover.Left

        .SeriesCollection(1).Select
        With .ChartGroups(1)
            .Overlap = 0
            .GapWidth = 0
            .HasSeriesLines = False
            .VaryByCategories = False
        End With
    End With

    'Add statistics

    With Graph_sheet
        r = num_bins + 4

        .Cells(r, 1) = "Average"
        .Cells(r, 2) = "=AVERAGE(Data!" & selected_range.Address & ")"

        .Cells(r, 4) = "Min"
        .Cells(r, 5) = Application.WorksheetFunction.Min(selected_range)

        .Cells(r, 7) = "Q1"
        .Cells(r, 8) = WorksheetFunction.Quartile(selected_range, 1)

        .Cells(r, 10) = "Median"
        .Cells(r, 11) = WorksheetFunction.Quartile(selected_range, 2)

        r = r + 1

        .Cells(r, 1) = "StdDev"
        .Cells(r, 2) = "=STDEV(Data!" & selected_range.Address & ")"

        .Cells(r, 4) = "Max"
        .Cells(r, 5) = Application.WorksheetFunction.Max(selected_range)

        .Cells(r, 7) = "Q3"
        .Cells(r, 8) = WorksheetFunction.Quartile(selected_range, 3)

        .Cells(r, 10) = "IQR"
        .Cells(r, 11) = WorksheetFunction.Quartile(selected_range, 3) _
            - WorksheetFunction.Quartile(selected_range, 1)

    End With

    With Application
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
        .EnableEvents = True
        .DisplayStatusBar = True
    End With

    Graph_sheet.Columns(1).AutoFit

End Sub

Код для получения точек осей x и y графика нормальности, которые могут создать плавную линию графика рассеяния XY для построения графика нормальности.

Sub GetNormalityData()

    Dim xMean As Variant
    Dim xSigma As Variant
    Dim xFirst As Variant
    Dim xLast As Variant
    Dim Nstep As Long
    Dim X As Variant
    Dim y As Variant
    Dim sRow As Long
    Dim StepValue As Variant

    ' enter values of mean, sigma, xfirst, xlast, Nstep
    With ActiveSheet
        xMean = .Range("B1")
        xSigma = .Range("B2")
        xFirst = .Range("B3")
        xLast = .Range("B4")
        Nstep = .Range("B5")
    End With

    StepValue = (xLast - xFirst) / (Nstep - 1)

    sRow = 0
    X = xFirst

    With Range("D1")
        Do While X <= xLast
            .Offset(sRow, 0) = X
            y = Application.WorksheetFunction.NormDist(X, xMean, xSigma, False)
            .Offset(sRow, 1) = y
            X = X + StepValue
            sRow = sRow + 1
        Loop
    End With

End Sub

Я также приложил пример рабочей книги на случай, если вам понадобится здесь . Чтобы получить графики, я сначала создал диаграмму нормального графика, а затем скопировал в нее значения числа гистограмм и изменил их на столбчатый кластерный график. Если есть какие-либо вопросы, которые вы хотите задать, пожалуйста, не стесняйтесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...