【问题标题】:PySpark - Sum a column in dataframe and return results as intPySpark - 在数据框中求和一列并将结果返回为 int
【发布时间】:2018-05-28 11:51:30
【问题描述】:

我有一个带有一列数字的 pyspark 数据框。我需要对该列求和,然后将结果返回为 python 变量中的 int。

df = spark.createDataFrame([("A", 20), ("B", 30), ("D", 80)],["Letter", "Number"])

我执行以下操作来对列求和。

df.groupBy().sum()

但我得到了一个数据框。

+-----------+
|sum(Number)|
+-----------+
|        130|
+-----------+

我会将 130 作为 int 返回,存储在一个变量中,以便在程序的其他地方使用。

result = 130

【问题讨论】:

    标签: python dataframe sum pyspark


    【解决方案1】:

    选择列作为RDD,滥用keys()获取Row中的值(或使用.map(lambda x: x[0])),然后使用RDD求和:

    df.select("Number").rdd.keys().sum()
    

    使用selectExpr的SQL求和:

    df.selectExpr("sum(Number)").first()[0]
    

    【讨论】:

      【解决方案2】:

      与其他答案类似,但不使用 groupby 或 agg。我只是选择有问题的列,对其求和,收集它,然后获取前两个索引以返回一个 int。我选择这个而不是接受的答案的唯一原因是我是 pyspark 的新手,并且对“数字”列没有明确地总结在接受的答案中感到困惑。如果我必须在一段时间后返回并尝试了解发生了什么,我会更容易理解以下语法。

      import pyspark.sql.functions as f   
      
      df.select(f.sum('Number')).collect()[0][0]
      

      【讨论】:

      • 这个问题的答案彼此相似,令人困惑。您能否在此处添加注释,解释这如何改进其他答案?
      【解决方案3】:

      您也可以尝试使用first() 函数。它返回数据帧的第一行,您可以使用索引访问各个列的值。

      df.groupBy().sum().first()[0]
      

      在您的情况下,结果是具有单行和单列的数据框,因此上述 sn-p 有效。

      【讨论】:

        【解决方案4】:

        如果你想要一个特定的列:

        import pyspark.sql.functions as F     
        
        df.agg(F.sum("my_column")).collect()[0][0]
        

        【讨论】:

        • 函数会返回一个数据框,我只需要int值。
        • 哦,是的,没看到细节,抱歉。我已经修改了
        • 现在返回一个列表
        【解决方案5】:

        有时会读取一个 csv 文件到 pyspark Dataframe,可能数字列更改为字符串类型 '23',像这样,你应该使用 pyspark.sql.functions.sum 来获取结果为 int ,而不是 sum()

        import pyspark.sql.functions as F                                                    
        df.groupBy().agg(F.sum('Number')).show()
        

        【讨论】:

          【解决方案6】:

          这是您可以做到这一点的另一种方式。使用aggcollect

          sum_number = df.agg({"Number":"sum"}).collect()[0]
          
          result = sum_number["sum(Number)"]
          

          【讨论】:

            【解决方案7】:

            最简单的方法真的:

            df.groupBy().sum().collect()
            

            但是操作很慢:Avoid groupByKey,你应该使用RDD和reduceByKey:

            df.rdd.map(lambda x: (1,x[1])).reduceByKey(lambda x,y: x + y).collect()[0][1]
            

            我尝试了更大的数据集并测量了处理时间:

            RDD 和 ReduceByKey:2.23 秒

            GroupByKey:30.5 秒

            【讨论】:

            • 太棒了!有效!但是如果我需要对所有列求和怎么办?我试图这样做: df.groupBy().sum().collect()[0].asDict() 但我的数据不适合内存,所以我试图使用你的提示作为解决方法。例如: list(map(lambda x: df.select(list(x)).groupBy().sum().collect()[0].asDict(), np.array_split(PossibleNulls, 10))) 工作!但是,太慢了;(
            【解决方案8】:

            我认为最简单的方法:

            df.groupBy().sum().collect()
            

            将返回一个列表。 在您的示例中:

            In [9]: df.groupBy().sum().collect()[0][0]
            Out[9]: 130
            

            【讨论】:

            • 它如何理解哪一列要分组,哪一列要总和?
            【解决方案9】:

            以下应该有效:

            df.groupBy().sum().rdd.map(lambda x: x[0]).collect()
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2021-06-29
              • 1970-01-01
              • 2021-08-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-01-08
              • 1970-01-01
              相关资源
              最近更新 更多