列数未知的组和总和CSV

时间:2019-01-17 14:17:55

标签: powershell

想知道是否有人可以帮助我。问题是我正在尝试导入,分组,求和和导出CSV。问题是我的CSV的以下格式的列数未知。

GroupA,GroupB,GroupC,ValueA,ValueB,ValueC,ValueD ...

GroupA,B和C是恒定的,我要分组的字段-我事先知道这些字段的名称。问题在于“值”列的数量未知-我想对它们全部求和(并且不预先知道它们的名称。)

如果我知道“值”字段的名称并且具有固定数量的“值字段”,那么我很乐意让此代码正常工作。但是我正在努力获取未知名称和列数的代码。

$csvImport = import-csv 'C:\input.csv'

$csvGrouped = $csvImport | Group-Object -property GroupA,GroupB,GroupC

$csvGroupedFinal = $csvGrouped | Select-Object @{Name = 'GroupA';Expression={$_.Values[0]}},
        @{Name = 'GroupB';Expression={$_.Values[1]}},
        @{Name = 'GroupC';Expression={$_.Values[2]}},                      
        @{Name = 'ValueA' ;Expression={
                ($_.Group|Measure-Object 'ValueA' -Sum).Sum
        }}

$csvGroupedFinal | Export-Csv 'C:\output.csv' -NoTypeInformation

示例输入数据-

GroupA, GroupB, Value A  
Sam, Apple, 10  
Sam, Apple, 20  
Sam, Orange, 50  
Ian, Apple, 15  

输出数据-

GroupA, GroupB, Value A  
Sam, Apple, 30  
Sam, Orange, 50  
Ian, Apple, 15

3 个答案:

答案 0 :(得分:1)

导入此脚本后,将属性(列)分为组/值

  • 它动态分组并仅对与数字无关的值字段求和

  • 输入顺序由最终的选择对象维护


## Q:\Test\2019\01\17\SO_54237887.ps1

$csvImport = Import-Csv '.\input.csv'

$Cols = ($csvImport[0].psobject.Properties).Name

# get list of group columns by name and wildcard
$GroupCols = $Cols | Where-Object {$_  -like 'Group*'}

# a different approach would be to select a number of leading columns
# $GroupCols = $Cols[0..1]

$ValueCols = $Cols | Where-Object {$_ -notin $GroupCols}
$OutCols = ,'Groups' + $ValueCols

$csvGrouped = $csvImport | Group-Object $GroupCols | ForEach-Object{
    $Props = @{Groups=$_.Name}
    ForEach ($ValCol in $ValueCols){
        $Props.Add($ValCol,($_.Group|Measure-Object $ValCol -Sum).Sum)
    }
    [PSCustomObject]$Props
}

$csvGrouped | Select-Object $OutCols

使用此示例输入文件

GroupA GroupB ValueA ValueB
------ ------ ------ ------
Sam    Apple  10     15
Sam    Apple  20     25
Sam    Orange 50     75
Ian    Apple  15     20

任意数量的组和值的样本输出

Groups      ValueA ValueB
------      ------ ------
Sam, Apple      30     40
Sam, Orange     50     75
Ian, Apple      15     20

不对代码进行任何更改,它也处理来自Hassans答案的数据:

Groups      ValueA ValueB ValueC
------      ------ ------ ------
Sam, Apple      30      4     20
Sam, Orange     50      4      5
Ian, Apple      15      3      3

答案 1 :(得分:1)

以下脚本应该起作用。请注意$FixedNames变量:

$csvImport = @"
Group A,Group B,Value A
sam,apple,10
sam,apple,20
sam,orange,50
ian,apple,15
"@ | ConvertFrom-Csv

$FixedNames  = @('Group A', 'Group B', 'Group C')
# $aux         = ($csvImport|Get-Member -MemberType NoteProperty).Name  ### sorted (wrong)
$aux         = ($csvImport[0].psobject.Properties).Name                 ### not sorted
$auxGrpNames = @( $aux     | Where-Object {$_    -in $FixedNames})
$auxValNames = @( $aux     | Where-Object {$_ -notin $FixedNames})
$csvGrouped  = $csvImport  | Group-Object -property $auxGrpNames
$csvGroupedFinal = $csvGrouped | 
    ForEach-Object {
        ($_.Name.Replace(', ',','), (($_.Group |
            Measure-Object -Property $auxValNames -Sum
                ).Sum -join ',')) -join ','
    } | ConvertFrom-Csv -Header $aux
$csvGroupedFinal

同样针对

进行了测试
$csvImport = @"
Group A,Group B,Value A,Value B
sam,apple,10,1
sam,apple,20,
sam,orange,50,5
ian,apple,15,51
"@ | ConvertFrom-Csv

,以及Group A,Group B,Group C,Value A,Value B标头的更复杂数据。

编辑已根据beneficial LotPings' comment更新。

答案 2 :(得分:0)

script1.ps1

Import-Csv 'input.csv' | `
Group-Object -Property GroupA,GroupB | `
% {$b=$_.name -split ', ';$c=($_.group | `
Measure-Object -Property Value* -Sum).Sum;
[PScustomobject]@{GroupA=$b[0];
GroupB=$b[1];
Sum=($c | Measure-Object -Sum).Sum }}

input.csv

GroupA, GroupB, ValueA, ValueB, ValueC
Sam, Apple, 10, 1, 10
Sam, Apple, 20, 3, 10
Sam, Orange, 50, 4, 5
Ian, Apple, 15, 3, 3

输出

PS D:\coding> .\script1.ps1

GroupA GroupB Sum
------ ------ ---
Sam    Apple   54
Sam    Orange  59
Ian    Apple   21