Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 从PySpark中的两个数据帧计算值_Python_Apache Spark_Pyspark - Fatal编程技术网

Python 从PySpark中的两个数据帧计算值

Python 从PySpark中的两个数据帧计算值,python,apache-spark,pyspark,Python,Apache Spark,Pyspark,我试图对PySpark(2.4)数据帧进行分组和求和,但无法逐个获得值 我有以下数据帧: data.groupBy("card_scheme", "failed").count().show() +----------------+------+------+ | card_Scheme|failed| count| +----------------+------+------+ | jcb| false| 4| |american express|

我试图对PySpark(2.4)数据帧进行分组和求和,但无法逐个获得值

我有以下数据帧:

data.groupBy("card_scheme", "failed").count().show()

+----------------+------+------+
|     card_Scheme|failed| count|
+----------------+------+------+
|             jcb| false|     4|
|american express| false| 22084|
|            AMEX| false|     4|
|      mastercard|  true|  1122|
|            visa|  true|  1975|
|            visa| false|126372|
|              CB| false|     6|
|        discover| false|  2219|
|         maestro| false|     2|
|            VISA| false|    13|
|      mastercard| false| 40856|
|      MASTERCARD| false|     9|
+----------------+------+------+
我试图为每个卡片方案计算公式
X=false/(false+true)
,但最后仍然得到一个数据帧

我期待着这样的事情:

| card_scheme | X |
|-------------|---|
| jcb         | 1 |
| ....        | . |
| visa        | 0.9846| (which is 126372 / (126372 + 1975)        
| ...         | . |
创建数据集

方法1:此方法速度较慢,因为它涉及通过
枢轴的传输

df=df.groupBy("card_Scheme").pivot("failed").sum("count")
df=df.withColumn('X',when((col('True').isNotNull()),(col('false')/(col('false')+col('true')))).otherwise(1))
df=df.select('card_Scheme','X')
df.show()
+----------------+------------------+
|     card_Scheme|                 X|
+----------------+------------------+
|            VISA|               1.0|
|             jcb|               1.0|
|      MASTERCARD|               1.0|
|         maestro|               1.0|
|            AMEX|               1.0|
|      mastercard|0.9732717137548239|
|american express|               1.0|
|              CB|               1.0|
|        discover|               1.0|
|            visa|0.9846120283294506|
+----------------+------------------+
方法2:使用SQL-您可以通过
windows
函数执行此操作。这会快得多

from pyspark.sql.window import Window
df = df.groupBy("card_scheme", "failed").agg(sum("count"))\
  .withColumn("X", col("sum(count)")/sum("sum(count)").over(Window.partitionBy(col('card_scheme'))))\
  .where(col('failed')== False).drop('failed','sum(count)')
df.show()

+----------------+------------------+
|     card_scheme|                 X|
+----------------+------------------+
|            VISA|               1.0|
|             jcb|               1.0|
|      MASTERCARD|               1.0|
|         maestro|               1.0|
|            AMEX|               1.0|
|      mastercard|0.9732717137548239|
|american express|               1.0|
|              CB|               1.0|
|        discover|               1.0|
|            visa|0.9846120283294506|
+----------------+------------------+

data.groupBy(“卡方案”).pivot(“失败”).agg(计数(“卡方案”))
应该可以工作。我不确定
agg(count(any_列))
,但线索是
pivot
函数。结果将得到两个新列:
false
true
。然后,您可以轻松地计算
x=false/(false+true)

一个简单的解决方案是执行第二个分组:

val grouped_df = data.groupBy("card_scheme", "failed").count() // your dataframe
val with_countFalse = grouped_df.withColumn("countfalse", when($"failed" === "false", $"count").otherwise(lit(0)))
with_countFalse.groupBy("card_scheme").agg(when($"failed" === "false", $"count").otherwise(lit(0)))) / sum($"count")).show()
其思想是,您可以创建第二列,该列在failed=false中包含failed,否则为0。这意味着count列的和为false+true,而countfalse的和为false。然后简单地进行第二次分组

注意:其他一些答案使用pivot。我相信pivot解决方案会更慢(它做的更多),但是,如果您选择使用它,请将特定值添加到pivot调用中,即pivot(“failed”、[“true”、“false”])以提高性能,否则spark将不得不执行两条路径(首先找到值)

创建2个新数据帧:

a = data.filter(col("failed") == "false").groupby("card_scheme").agg(func.sum("count").alias("num"))
b = data.groupby("card_scheme").agg(func.sum("count").alias("den"))
c = a.join(b, a.card_scheme == b.card_scheme).drop(b.card_scheme)
df_true = data.filter(data.failed == True).alias("df1")
df_false =data.filter(data.failed == False).alias("df2")
连接两个数据帧:

a = data.filter(col("failed") == "false").groupby("card_scheme").agg(func.sum("count").alias("num"))
b = data.groupby("card_scheme").agg(func.sum("count").alias("den"))
c = a.join(b, a.card_scheme == b.card_scheme).drop(b.card_scheme)
df_true = data.filter(data.failed == True).alias("df1")
df_false =data.filter(data.failed == False).alias("df2")
将一列与另一列分开:

c.withColumn('X', c.num/c.den)

首先将根数据帧拆分为两个数据帧:

a = data.filter(col("failed") == "false").groupby("card_scheme").agg(func.sum("count").alias("num"))
b = data.groupby("card_scheme").agg(func.sum("count").alias("den"))
c = a.join(b, a.card_scheme == b.card_scheme).drop(b.card_scheme)
df_true = data.filter(data.failed == True).alias("df1")
df_false =data.filter(data.failed == False).alias("df2")
然后进行完全外部连接,我们可以得到最终结果:

from pyspark.sql.functions import col,when
df_result = df_true.join(df_false,df_true.card_scheme == df_false.card_scheme, "outer") \
    .select(when(col("df1.card_scheme").isNotNull(), col("df1.card_scheme")).otherwise(col("df2.card_scheme")).alias("card_scheme") \
            , when(col("df1.failed").isNotNull(), (col("df2.count")/(col("df1.count") + col("df2.count")))).otherwise(1).alias("X"))

无需执行
groupby
,只需额外添加两个数据帧并加入即可。

好吧,这与我想要的非常接近,但这有时会给我“null”值,这非常完美!不需要改变任何东西:)真的很有帮助!非常感谢:)您的代码将完美地工作,并将解决手头的问题。我只想说一句话-
连接
如果数据存储在多个分区上,那么操作成本相当高,因为这将涉及一次洗牌。其中,
groupBy
可以先在本地分区上进行分组,然后再进行洗牌。因此,被洗牌的行数将大大减少,从而提高了处理的效率。你好,是的。我同意:)