none
вычисления в командной строке (powershell) операции с суммой средних арифметических значений массива RRS feed

  • Вопрос

  • отдельно спасибо товарищу Kazun.

    продолжение темы

    https://social.technet.microsoft.com/Forums/ru-RU/64b1a61d-d6f0-4269-a4f0-79bac2e87eaf/-powershell-vba?forum=scrlangru


    ссылка на файл:

    http://rgho.st/7ds8YFvFN

    вопрос такой: как будет выглядеть скрипт в котором расчёт будет проводиться так - в пределах одного дня (равное значение столбца 1) значения строк будут рассчитываться с учётом среднего арифметического, в excel выглядит так:

    =ОКРУГЛ(((RC[-2]-R[-1]C[-2])*1440-1)*(RC[-1]+R[-1]C[-1])/2+RC[-1];1)

    или

    =ОКРУГЛ(((B2-B1)*1440-1)*(C2+C1)/2+C2;1)

    столбец B - второй столбец - время, C - третий столбец - значения.

    затем скорректированные значения за день будут суммироваться, сумму нужно  умножить на 3 и разделить на 500, округлить до 0 знака после запятой (если можно показать как округлять до 1, 2, 3 знака после запятой).

    результат вывести в файл в таком виде:

    04.08.16,1557,732 05.08.16,2297,1369


    где столбец 2 - наши вычисления, 3 - количество строк за день.

    спасибо.



    • Изменено Morn1ng 9 сентября 2016 г. 10:03 корректировка
    9 сентября 2016 г. 9:50

Ответы

  • $d = import-csv .\sol_data.csv -Header 1,2,3
    $data = @()
    $data += $d[0]
    $data += for($i=1;$i -lt $d.count;$i++) {
    	$t1 = Get-Date ($d[$i]."2" + " " + $d[$i]."1")
    	$t2 = Get-Date ($d[$i-1]."2" + " " + $d[$i-1]."1")
        [int]$t = ([int]($t1 - $t2 ).Minutes) - 1
    	[long]$m = $t * ([int]$d[$i]."3" + [int]$d[$i-1]."3") / 2 + [int]$d[$i]."3"
        [pscustomobject] @{
            "1" = $d[$i]."1"
            "2" = $d[$i]."2"
            "3" = [math]::Round($m,1)
        }
    } 
    $data | Group {$_."1"} | Foreach {
        $sum = ($_.Group | Foreach {[long]$_."3"} | Measure-Object -Sum).Sum * 3 / 500
        $sum = [Math]::Round($sum, 0)
        "{0},{1},{2}" -f $_.Name,$sum,$_.Count
    } | Out-File result.txt 

    • Помечено в качестве ответа Morn1ng 9 сентября 2016 г. 12:37
    9 сентября 2016 г. 12:31
    Отвечающий

Все ответы

  • $d = import-csv .\sol_data.csv -Header 1,2,3
    $data = @()
    $data += $d[0] 
    $data += for($i=1;$i -lt $d.count;$i++) {
    	$t1 = Get-Date ($d[$i]."2" + " " + $d[$i]."1")
    	$t2 = Get-Date ($d[$i-1]."2" + " " + $d[$i-1]."1")
    	$m = (($t1 - $t2).Minutes * 1440 - 1) * (([int]$d[$i]."3" + [int]$d[$i-1]."3") / 2 + [int]$d[$i]."3")
        [pscustomobject] @{
            "1" = $d[$i]."1"
            "2" = $d[$i]."2"
            "3" = [math]::Round($m,1)
        }
    } 
    $data | Group {$_."1"} | Foreach {
        $sum = ($_.Group | Foreach {[long]$_."3"} | Measure-Object -Sum).Sum * 3 / 500
        $sum = [Math]::Round($sum, 0)
        "{0},{1},{2}" -f $_.Name,$sum,$_.Count
    } | Out-File result.txt 

    Округлять:

    PS > [Math]::Round
    
    OverloadDefinitions
    -------------------
    static double Round(double a)
    static double Round(double value, int digits)
    
    PS > [Math]::Round("1.11")
    1
    PS > [Math]::Round("1.11",0)
    1
    PS > [Math]::Round("1.11",1)
    1,1
    PS > [Math]::Round("1.11",2)
    1,11

    9 сентября 2016 г. 10:43
    Отвечающий
  • установленная версия Powershell 3

    считает не то.

    результат должен быть:

    04.08.16,1555,732
    05.08.16,2298,1369
    06.08.16,2278,1363

    или до применения операции *3/500:

    04.08.16,259205,732
    05.08.16,383023,1369
    06.08.16,379639,1363
    в последних цифрах может немного разниться за счёт округления

    по факту получается результат:

    04.08.16,4469884,732
    05.08.16,6612901,1369
    06.08.16,6556115,1363

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

    1/2=1*0,5

    1/500=1*0,002

    если адекватно себя ведёт с дробями при расчётах - не забывает значения после целых то округление можно оставить только на самой последней операции или отбрасывать значение после целых.

    в первой части расчётов важен промежуточный учёт десятых, на этапе *3/500 важна целая часть за день.

    9 сентября 2016 г. 11:42
  • 11:13 - 11:12 = 1 или 0?

    (B2-B1)*1440-1) на примерах B2-B1, что с ними

    9 сентября 2016 г. 11:55
    Отвечающий
  • (11:13 - 11:12) * 1440 = 1

    так excel считает, что для получения целого числа (в данном случае 1 число-коэффициент умножения = 1 секунда) разницу минут нужно умножить на 1440

    логика такая если пропущенх минут нет то разница составляет 1. мы отнимаем единицу (получем 0) и умножаем на среднее арифметическое значений текущей и предидуйщей строки (654+654)/2 в итоге чстного случая получаем 0, к которому добавляем значение текущей строки.

    если же есть пропущеная минута (11:27 - 11:25) *1440 = 2

    из которого мы вычитаем 1 и получаем 1 (потерянная минута), затем умножаем на (775+770)/2 получаем 772,5, добавляем значение текущей строки 775 и получаем 1547,5

        $t1 = Get-Date ($d[$i]."2" + " " + $d[$i]."1")
        $t2 = Get-Date ($d[$i-1]."2" + " " + $d[$i-1]."1")
        $m = [int]$d[$i]."3" * ($t1 - $t2).Minutes

    здесь не было умножения на 1440. говорилось что эти значения - время.

    • Изменено Morn1ng 9 сентября 2016 г. 12:27 уточнение
    9 сентября 2016 г. 12:24
  • $d = import-csv .\sol_data.csv -Header 1,2,3
    $data = @()
    $data += $d[0]
    $data += for($i=1;$i -lt $d.count;$i++) {
    	$t1 = Get-Date ($d[$i]."2" + " " + $d[$i]."1")
    	$t2 = Get-Date ($d[$i-1]."2" + " " + $d[$i-1]."1")
        [int]$t = ([int]($t1 - $t2 ).Minutes) - 1
    	[long]$m = $t * ([int]$d[$i]."3" + [int]$d[$i-1]."3") / 2 + [int]$d[$i]."3"
        [pscustomobject] @{
            "1" = $d[$i]."1"
            "2" = $d[$i]."2"
            "3" = [math]::Round($m,1)
        }
    } 
    $data | Group {$_."1"} | Foreach {
        $sum = ($_.Group | Foreach {[long]$_."3"} | Measure-Object -Sum).Sum * 3 / 500
        $sum = [Math]::Round($sum, 0)
        "{0},{1},{2}" -f $_.Name,$sum,$_.Count
    } | Out-File result.txt 

    • Помечено в качестве ответа Morn1ng 9 сентября 2016 г. 12:37
    9 сентября 2016 г. 12:31
    Отвечающий
  • спасибо за оказанную помощь.

    работает отлично.

    9 сентября 2016 г. 12:52