Свертывание 10-периодной кривой до 4-х периодной

У меня есть таблица кривой затрат за 10 периодов ниже. Как мне программно свернуть / сжать / сжать это до 4 периодов. Я использую VBA, но у меня должна быть возможность следить за другими языками. Этот распорядок должен работать в течение любого периода, который вы к нему переходите. Например, если я поставлю ему 7, он должен сжать проценты до 7 периодов. Если я пропущу 24, увеличьте процентное соотношение до 24 периодов, распределив проценты на основе исходной кривой. Любая помощь или пример будут оценены. Спасибо...

ORIGINAL
Period  Pct
1       10.60%
2       19.00%
3       18.30%
4       14.50%
5       10.70%
6        8.90%
7        6.50%
8        3.10%
9        3.00%
10       5.40%
COLLAPSED
Period  Pct
1       38.75%
2       34.35%
3       16.95%
4        9.95%

РЕДАКТИРОВАТЬ: Я добавил образец кода ниже относительно того, что у меня есть до сих пор. Он работает только для периодов 1, 2, 3, 5, 9, 10. Может быть, кто-нибудь поможет изменить его, чтобы он работал на любой период. Отказ от ответственности, я не программист, поэтому у меня плохое кодирование. К тому же я понятия не имею, что делаю.

Sub Collapse_Periods()
    Dim aPct As Variant
    Dim aPer As Variant
    aPct = Array(0.106, 0.19, 0.183, 0.145, 0.107, 0.089, 0.065, 0.031, 0.03, 0.054)
    aPer = Array(1, 2, 3, 5, 9, 10)
    For i = 0 To UBound(aPer)
        pm = 10 / aPer(i)
        pct1 = 1
        p = 0
        ttl = 0
        For j = 1 To aPer(i)
            pct = 0
            k = 1
            Do While k <= pm
                pct = pct + aPct(p) * pct1
                pct1 = 1
                p = p + 1
                If k <> pm And k = Int(pm) Then
                    pct1 = (pm - Int(pm)) * j
                    pct = pct + (pct1 * aPct(p))
                    pct1 = 1 - pct1
                End If
                k = k + 1
            Loop
            Debug.Print aPer(i) & " : " & j & " : " & pct
            ttl = ttl + pct
        Next j
        Debug.Print "Total:  " & ttl
    Next i
End Sub

person Txoov    schedule 15.05.2011    source источник
comment
Вы знаете, как интегрировать функцию?   -  person Dr. belisarius    schedule 15.05.2011
comment
Не уверены, что вы имеете в виду, интегрировать функцию?   -  person Txoov    schedule 16.05.2011
comment
Я имею в виду это en.wikipedia.org/wiki/Integral   -  person Dr. belisarius    schedule 16.05.2011
comment
Похоже на исчисление снова и снова. Над моей головой. Все еще не уверен, как бы вы это реализовали. Спасибо...   -  person Txoov    schedule 17.05.2011


Ответы (2)


введите здесь описание изображения

person Dr. belisarius    schedule 17.05.2011
comment
Мне нравится разница в 6 строках и слишком многих в VBA! - person ; 18.05.2011
comment
@osknows После изучения Mathematica я действительно ненавижу, когда мне приходится писать формулы на других языках. Кстати, вся проблема действительно однострочная, если вы используете функциональную нотацию, но я не хотел использовать ее здесь, потому что она намного более неясна. - person Dr. belisarius; 18.05.2011
comment
Ваша формула - это именно то, что я искал. Мне следовало уделять больше внимания математике. Спасибо за вашу помощь, я очень ценю это. - person Txoov; 18.05.2011

Я хотел бы знать, как это делается также с помощью Integral? Вот как я бы это сделал - возможно, это длинный / длинный метод, но я хотел бы увидеть несколько лучших предложений.

Вероятно, проще сначала увидеть метод в Excel, используя функцию ЛИНЕЙН и Именованные диапазоны. Я предположил, что функция логарифмическая. Я обрисовал в общих чертах шаги [1.] - [5.] введите здесь описание изображения

Затем этот код VBA по существу реплицирует метод Excel, используя функцию для передачи 2 массивов, точек и возвращаемого массива, который может быть записан в диапазон

Sub CallingProc()
Dim Periods As Long, returnArray() As Variant
Dim X_Values() As Variant, Y_Values() As Variant

Periods = 4
ReDim returnArray(1 To Periods, 1 To 2)

With Sheet1
    X_Values = Application.Transpose(.Range("A2:A11"))
    Y_Values = Application.Transpose(.Range("B2:B11"))
End With


FGraph X_Values, Y_Values, Periods, returnArray 'pass 1D array of X, 1D array of Y,    Periods, Empty ReturnArray
End Sub


Function FGraph(ByVal x As Variant, ByVal y As Variant, ByVal P As Long, ByRef returnArray As Variant)
Dim i As Long, mConstant As Double, cConstant As Double

'calc cumulative Y and take Ln (Assumes Form of Graph is logarithmic!!)
For i = LBound(y) To UBound(y)
    If i = LBound(y) Then
        y(i) = y(i)
    Else
        y(i) = y(i) + y(i - 1)
    End If

    x(i) = Log(x(i))
Next i

'calc line of best fit
With Application.WorksheetFunction
    mConstant = .LinEst(y, x)(1)
    cConstant = .LinEst(y, x)(2)
End With

'redim array to fill for new Periods
ReDim returnArray(1 To P, 1 To 2)

'Calc new periods based on line of best fit
For i = LBound(returnArray, 1) To UBound(returnArray, 1)
    returnArray(i, 1) = UBound(y) / P * i
    If i = LBound(returnArray, 1) Then
        returnArray(i, 2) = (Log(returnArray(i, 1)) * mConstant) + cConstant
    Else
        returnArray(i, 2) = ((Log(returnArray(i, 1)) * mConstant) + cConstant) - _
        ((Log(returnArray(i - 1, 1)) * mConstant) + cConstant)
    End If
Next i

'returnArray can be written to range

End Function

РЕДАКТИРОВАТЬ:

Этот код VBA теперь вычисляет линейный тренд точек по обе стороны от нового сокращения периода. Данные возвращаются в двумерном массиве с именем returnArray.

Sub CallingProc()
Dim Periods As Long, returnArray() As Variant
Dim X_Values() As Variant, Y_Values() As Variant

Periods = 4
ReDim returnArray(1 To Periods, 1 To 2)

With Sheet1
    X_Values = Application.Transpose(.Range("A2:A11"))
    Y_Values = Application.Transpose(.Range("B2:B11"))
End With


FGraph X_Values, Y_Values, returnArray 'pass 1D array of X, 1D array of Y, Dimensioned  ReturnArray
End Sub


Function FGraph(ByVal x As Variant, ByVal y As Variant, ByRef returnArray As Variant)
Dim i As Long, j As Long, mConstant As Double, cConstant As Double, Period As Long

Period = UBound(returnArray, 1)

'calc cumulative Y
For i = LBound(y) + 1 To UBound(y)
        y(i) = y(i) + y(i - 1)
Next i

'Calc new periods based on line of best fit
For i = LBound(returnArray, 1) To UBound(returnArray, 1)
    returnArray(i, 1) = UBound(y) / Period * i

        'find position of new period to return adjacent original data points
        For j = LBound(x) To UBound(x)
          If returnArray(i, 1) <= x(j) Then Exit For
        Next j

        'calc linear line of best fit between existing data points
        With Application.WorksheetFunction
            mConstant = .LinEst(Array(y(j), y(j - 1)), Array(x(j), x(j - 1)))(1)
            cConstant = .LinEst(Array(y(j), y(j - 1)), Array(x(j), x(j - 1)))(2)
        End With

        returnArray(i, 2) = (returnArray(i, 1) * mConstant) + cConstant

Next i

'returnarray holds cumulative % so calc period only %
For i = UBound(returnArray, 1) To LBound(returnArray, 1) + 1 Step -1
    returnArray(i, 2) = returnArray(i, 2) - returnArray(i - 1, 2)
Next i

'returnArray now holds your data

End Function

Возврат:

Свернут

1 38.75%

2 34.35%

3 16.95%

4 9.95%

person Community    schedule 17.05.2011
comment
@osknows, спасибо за ваши усилия. Я думаю, вы на правильном пути; однако ваши свернутые 4 периода не равны 100%, и они не соответствуют тому, что я ожидаю от 4 процентов. - person Txoov; 17.05.2011
comment
@Txoov - как вы рассчитывали проценты? Мой метод основан на предположении, что функция является логарифмической, что может не подходить наилучшим образом. Поскольку предположение не имеет R2 = 1, будут некоторые вариации, а также, поскольку периоды меньше, чем у оригинала, это эффективно снижает дискретизацию и теряет разрешение. - person ; 17.05.2011
comment
@osknows Я думаю, он линейно интерполирует точки. Смотрите мой ответ. - person Dr. belisarius; 17.05.2011
comment
@belisarius - хороший метод ниже! Это даже проще, чем я думал тогда, когда у вас есть 4 периода (2,5,5,7,5 и 10), просто нанесите их на линейный тренд двух точек данных по обе стороны от оригинала. Например, для P1 2,5 постройте 2,29,6% и 3,47,9% и найдите Y для 2,5 ((2,5 * 0,183) -0,07 = 38,75%) - person ; 17.05.2011
comment
@osknows, спасибо за отредактированный пример. Похоже, это должно сработать, но метод Велизария работает лучше для меня, так как я не хочу полагаться на функции Excel. Еще раз спасибо за вашу помощь. - person Txoov; 18.05.2011
comment
@Txoov Помните, что вы можете (и должны) голосовать за полезные ответы, подобные этому, using the gray triangles, поскольку доверие к системе основано на репутации, которую пользователи получают, делясь своими знаниями. - person Dr. belisarius; 18.05.2011
comment
@belisarius, я пытался, но я новичок и у меня пока недостаточно репутации. Я вернусь, чтобы проголосовать, когда наберу достаточно. Спасибо еще раз. - person Txoov; 18.05.2011
comment
@Txoov Поздравляю с первым достижением репутации! - person Dr. belisarius; 18.05.2011
comment
@belisarius Вот почему я вмешался, так как хотел узнать, как это лучше сделать - спасибо! Я также думал сегодня, что это также можно решить с помощью простой тригонометрии, поскольку эффективно вычисляется новая «противоположная» высота. - person ; 20.05.2011
comment
@osknows Если вы посмотрите мою формулу для f [x_], вы увидите такой термин, как a[Ceiling[]]-a[Floor[]]. Это представляет собой тангенс угла для верхних треугольников кривой накопления. Так что да, это замаскированная тригонометрическая формула. - person Dr. belisarius; 20.05.2011