Агрегирование задач по продолжительности для каждого дня недели / месяца?(POSH) - PullRequest
0 голосов
/ 08 июня 2018

Я анализирую JSON из веб-службы, чтобы получить мои задачи (используя TimeFlip).Прямо сейчас я возвращаюсь к каждой задаче, когда она возникла, и по продолжительности, поэтому данные выглядят следующим образом:

(taskname, start, durationinSec)
TaskA,"6/5/2018 12:16:36 PM",312
TaskB,"6/5/2018 12:30:36 PM",200
TaskA,"6/6/2018 08:00:00 AM",150
TaskA,"6/6/2018 03:00:00 PM",150
(etc etc)

Я хотел бы создать сводный отчет, показывающий по дням, у каких задач было сколько времени,

Несмотря на то, что данные будут охватывать недели, я просто пытаюсь сделать еженедельный отчет, который я могу легко перенести в наше приложение времени (так как они не дают мне ключ API).Поэтому сначала я сделаю что-то вроде where {$_.start -gt (? {$_.start -gt (get-date -Hour 0 -Minute 00 -Second 00).adddays(-7)}.

       6/5/2018    6/6/2018
 TaskA 312         300
 TaskB 200      

Как я могу это сделать?Я предполагаю, что group-object, но неясно, как бы вы делали опору или даже группировку.

Ответы [ 2 ]

0 голосов
/ 10 июня 2018

Поиск в Google для PowerShell и Pivot Я нашел этот gist.github.com с более универсальным способом создания сводной таблицы.
Для транспонирования (swap x, y) вы просто меняетепеременные $rotate, $keep
Имеет дополнительное преимущество вычисления строки Итого

## Q:\Test\2018\06\09\PivotTable.ps1
## Source https://gist.github.com/andyoakley/1651859
# #############################################################################
# Rotates a vertical set similar to an Excel PivotTable 
# #############################################################################
$OutputFile = "MyPivot.csv"

$data = @'
taskname,start,duration
TaskA,"6/5/2018 12:16:36 PM",312
TaskB,"6/5/2018 12:30:36 PM",200
TaskA,"6/6/2018 08:00:00 AM",150
TaskA,"6/6/2018 03:00:00 PM",150
'@ | ConvertFrom-Csv |Select-Object taskname, duration, @{n='start';e={($_.start -split ' ')[0]}}

# Fields of interest
$rotate = "taskname"  # Bits along the top
$keep   = "start"     # Those along the side
$value  = "duration"  # What to total

#-------------------- No need to change anything below ------------------------

# Creatre variable to store the output
$rows = @()

# Find the unique "Rotate" [top row of the pivot] values and sort ascending
$pivots = $data | select -unique $rotate | foreach { $_.$rotate} | Sort-Object

# Step through the original data...
#  for each of the "Keep" [left hand side] find the Sum of the "Value" for each "Rotate"

$data | 
    group $keep  | 
    foreach { 
        $group = $_.Group 
        # Create the data row and name it as per the "Keep"
        $row = new-object psobject
        $row | add-member NoteProperty $keep $_.Name 
        # Cycle through the unique "Rotate" values and get the sum
        foreach ($pivot in $pivots) {
            $row | add-member NoteProperty $pivot ($group | where { $_.$rotate -eq $pivot } | measure -sum $value).Sum
        }
        # Add the total to the row
        $row | add-member NoteProperty Total ($group | measure -sum $value).Sum
        # Add the row to the collection 
        $rows += $row
    } 

# Do something with the pivot rows
$rows | Format-Table
$rows | Export-Csv $OutputFile -NoTypeInformation

Пример выходных данных:

start    TaskA TaskB Total
-----    ----- ----- -----
6/5/2018   312   200   512
6/6/2018   300         300

Или обмен x / y

taskname 6/5/2018 6/6/2018 Total
-------- -------- -------- -----
TaskA         312      300   612
TaskB         200            200
0 голосов
/ 08 июня 2018

Следующее не выводит сводную таблицу, но выполняет желаемую группировку и агрегирование :

$rows = @'
taskname,start,durationinSec
TaskA,"6/5/2018 12:16:36 PM",312
TaskB,"6/5/2018 12:30:36 PM",200
TaskA,"6/6/2018 08:00:00 AM",150
TaskA,"6/6/2018 03:00:00 PM",150
'@ | ConvertFrom-Csv

$rows | Group-Object { (-split $_.start)[0] }, taskname | ForEach-Object {
  $_ | Select-Object @{ n='Date'; e={$_.Values[0]} }, 
                     @{ n='Task'; e={$_.Values[1]} }, 
                     @{ n='Duration'; e={ ($_.Group | Measure-Object durationInSec -Sum).Sum } } 
}

(-split $_.start)[0] разбивает каждое значение start на пробелы и возвращаетпервый токен ([0]), который является частью даты метки времени;например, 6/5/2018 возвращается для 6/5/2018 12:16:36 PM;передача этой операции в виде блока сценария ({ ... }) в Group-Object означает, что группировка происходит только по дате, а не по времени (в дополнение к группированию по taskname).

Это приводит к:

Date     Task  Duration
----     ----  --------
6/5/2018 TaskA      312
6/5/2018 TaskB      200
6/6/2018 TaskA      300

Чтобы построить вывод, подобный сводной таблице , требуется значительно больше усилий, и он не будет быстрым:

Предположим, что $objs содержит объектысозданный выше ($objs = $rows | Group-Object ...).

# Get all distinct dates.
$dates = $objs | Select-Object -Unique -ExpandProperty Date
# Get all distinct tasks.
$tasks = $objs | Select-Object -Unique -ExpandProperty Task

# Create an ordered hashtable that contains an entry for each task that
# holds a nested hashtable with (empty-for-now) entries for all dates.
$ohtPivot = [ordered] @{}
$tasks | ForEach-Object {
  $ohtDates = [ordered] @{}
  $dates | ForEach-Object { $ohtDates[$_] = $null }
  $ohtPivot[$_] = $ohtDates
}

# Fill the hashtable from the grouped objects with the task- and 
# date-specific durations.
$objs | ForEach-Object { $ohtPivot[$_.Task][$_.Date] = $_.Duration }

# Output the resulting hashtable in pivot-table-like form by transforming
# each entry into a custom object
$ohtPivot.GetEnumerator() | ForEach-Object {
  [pscustomobject] @{ Task = $_.Key } | Add-Member -PassThru -NotePropertyMembers $_.Value
}

Вышеуказанные выходы:

Task  6/5/2018  6/6/2018
----  --------  --------
TaskA      312      300
TaskB      200         
...