你如何使用Seq。按F#中的函数求平均值,以平均一行中的数据,并按另一行中的数据分组?

你如何使用Seq。按F#中的函数求平均值,以平均一行中的数据,并按另一行中的数据分组?,f#,F#,我有两排,州和收入。有多行具有相同的状态,但我希望每个状态有一行。因此,我希望按州平均所有收入数据,这样我可以得到每个州的平均值,每个州只有一个值/行。这是我试图将收入行中的值按州进行平均的尝试。 我将序列分组如下: Seq.groupBy(有趣的行->行状态) 但是,当我尝试平均收入列中已按州分组的数据时(从上面): 序号平均值(乐趣行->收入行) 它给了我这个错误: 错误FS0001:应为支持运算符“+”的类型,但给定了函数类型。函数可能缺少参数 我做错了什么?如果您想传入函数,您需要,而不

我有两排,州和收入。有多行具有相同的状态,但我希望每个状态有一行。因此,我希望按州平均所有收入数据,这样我可以得到每个州的平均值,每个州只有一个值/行。这是我试图将收入行中的值按州进行平均的尝试。 我将序列分组如下:

Seq.groupBy(有趣的行->行状态)

但是,当我尝试平均收入列中已按州分组的数据时(从上面):

序号平均值(乐趣行->收入行)

它给了我这个错误:

错误FS0001:应为支持运算符“+”的类型,但给定了函数类型。函数可能缺少参数


我做错了什么?

如果您想传入函数,您需要,而不是
Seq.average
接受一个数字序列,而
Seq.averageBy
接受一个函数和一个类型为T的事物序列(该函数应该是一个接受类型为T的事物并返回数字的函数)

另外,如果您首先使用
Seq.groupBy
,请注意它返回一个元组序列,其中元组的第一个元素是键,第二个元素是具有该键的值序列。(在类型签名中,这由类型
seq>
表示)。所以你想要的有点复杂,我会带你看一下:

  • 首先,如果您想获得整个序列的平均值,那么它将是
    rows |>Seq.averageBy(fun row->row.Income)
  • 但首先,您要调用
    Seq.groupBy
    ,它返回一个元组序列。如果您执行了
    rows |>Seq.groupBy(fun row->row.State)|>Seq.averageBy(fun row->row.Income)
    ,那么您会收到一个错误,说明元组没有名为
    Income
    的属性。因为
    Seq.groupBy
    调用已将您的数据转换为如下内容:

    seq {
        (TX, seq { row1, row4, row7 })
        (CA, seq { row2, row5, row8 })
        (NY, seq { row3, row6, row9 })
    }
    
    rows
    |> Seq.groupBy (fun row -> row.State)
    |> Seq.map (fun (state, groupedRows) ->
        let averageIncome = groupedRows |> Seq.averageBy (fun row -> row.Income)
        (state, averageIncome))
    
  • 最后你想要的是:

    seq {
        (TX, 12345.0)
        (CA, 34567.0)
        (NY, 23456.0)
    }
    
  • 因此,您需要的是获取由
    Seq.groupBy
    生成的序列,并以保留键但转换值序列的方式对其进行转换。每当你想“我想保持这个序列,但把它的内容变成其他东西”,你就会想要

  • Seq.map
    接受一个函数,该函数接受一个类型为T的项(不管T可能是什么),但我们可以使用(查找该页面上的
    addOneToTuple
    示例)使其更简单:因为我们知道我们映射的“外部”序列是一个
    (键,值)
    的元组,所以我们可以编写该函数来接受
    (key,values)
    tuple:
    fun(key,values)->key,(values |>Seq.averageBy…)
    就是你想要的
  • 因此,您要使用的管道,首先分组,然后平均每个组中的值(同时保留组键),如下所示:

    seq {
        (TX, seq { row1, row4, row7 })
        (CA, seq { row2, row5, row8 })
        (NY, seq { row3, row6, row9 })
    }
    
    rows
    |> Seq.groupBy (fun row -> row.State)
    |> Seq.map (fun (state, groupedRows) ->
        let averageIncome = groupedRows |> Seq.averageBy (fun row -> row.Income)
        (state, averageIncome))
    
  • 注意,在最后的
    Seq.map
    步骤中,我必须确保返回
    (state,averageIncome)
    ;如果我刚刚返回了
    groupedRows |>Seq.averageBy(fun row->row.Income)的结果
    ,那么我将把一个元组映射成一个值,你将得到一个平均收入的序列,而该序列不再附带州


    我希望这能帮助您了解如何在F#中解决类似问题的过程。有,而且一开始可能会有点混乱。但无论您是初学者还是有经验的F#开发人员,基本方法都是一样的:您首先要说“我拥有什么样的数据,以及我完成后想要拥有什么样的数据?”然后,您寻找一个具有正确“形状”的函数,将类型a的数据转换为类型B的数据;如果没有单一的函数,您可以将多个函数(如构建块)组合在一起,以获得所需的整体函数。(例如,我们如何组合
    Seq.map
    Seq.averageBy
    ).

    如果你想传入一个函数,你想要,而不是。
    Seq.average
    接受一个数字序列,而
    Seq.averageBy
    接受一个函数和一个类型为T的序列(函数应该是一个接受类型为T的东西并返回一个数字的函数)

    另外,如果您首先使用
    Seq.groupBy
    ,请注意它返回一个元组序列,其中元组的第一个元素是键,第二个元素是具有该键的值序列。(在类型签名中,这由类型
    Seq>
    表示).所以你想要的东西有点复杂,我会带你走过去:

  • 首先,如果您想获得整个序列的平均值,那么它将是
    rows |>Seq.averageBy(fun row->row.Income)
  • 但首先,您调用的是
    Seq.groupBy
    ,它返回一系列元组。如果调用了
    rows |>Seq.groupBy(fun row->row.State)|>Seq.averageBy(fun row->row.Income)
    ,则会出现一个错误,指出元组没有名为
    Income
    的属性。因为
    Seq.groupBy
    调用已将您的数据转换为如下内容:

    seq {
        (TX, seq { row1, row4, row7 })
        (CA, seq { row2, row5, row8 })
        (NY, seq { row3, row6, row9 })
    }
    
    rows
    |> Seq.groupBy (fun row -> row.State)
    |> Seq.map (fun (state, groupedRows) ->
        let averageIncome = groupedRows |> Seq.averageBy (fun row -> row.Income)
        (state, averageIncome))
    
  • 最后你想要的是:

    seq {
        (TX, 12345.0)
        (CA, 34567.0)
        (NY, 23456.0)
    }
    
  • 因此,您需要的是获取由
    Seq.groupBy
    生成的序列,并以一种保留键但转换值序列的方式对其进行转换。每当您认为“我想保留此序列,但将其内容转换为其他内容”时,您都需要

  • Seq.map
    接受一个函数,该函数接受一个类型为T的项(不管T可能是什么),但我们可以使用(查找该页面上的
    addOneToTuple
    示例)使其更简单:因为我们知道我们映射的“外部”序列是一个
    (键,值)
    的元组