Рассчитать значения из двух фреймов данных в PySpark - PullRequest
0 голосов
/ 03 января 2019

Я пытаюсь сгруппировать и суммировать для кадра данных 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 и все же получить один кадр данных в конце.

Я ожидаю что-то вроде:

| card_scheme | X |
|-------------|---|
| jcb         | 1 |
| ....        | . |
| visa        | 0.9846| (which is 126372 / (126372 + 1975)        
| ...         | . |

Ответы [ 5 ]

0 голосов
/ 04 января 2019

Первый разделить корневой фрейм данных на два фрейма:

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, просто добавьте два дополнительных кадра данных и присоединитесь.

0 голосов
/ 03 января 2019
from pyspark.sql import functions as func
from pyspark.sql.functions import col    
data = data.groupby("card_scheme", "failed").count()

Создайте 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)

Разделите один столбец на другой:

c.withColumn('X', c.num/c.den)
0 голосов
/ 03 января 2019

data.groupBy("card_scheme").pivot("failed").agg(count("card_scheme")) должно работать.Я не уверен насчет agg(count(any_column)), но ключом является pivot функция.В результате вы получите два новых столбца: false и true.Тогда вы можете легко рассчитать x = false / (false + true).

0 голосов
/ 03 января 2019

Простым решением было бы сделать второй groupby:

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()

Идея состоит в том, что вы можете создать второй столбец, в котором с ошибкой имеется сбой = false и 0 в противном случае.Это означает, что сумма столбца count дает вам false + true, а сумма countfalse дает только false.Затем просто сделайте вторую группу по

Примечание: в некоторых других ответах используется сводка.Я полагаю, что сводное решение будет медленнее (оно делает больше), однако, если вы решите использовать его, добавьте конкретные значения к вызову сводки, т.е. pivot («fail», [«true», «false»])для повышения производительности, в противном случае спарк должен был бы сделать два пути (первый, чтобы найти значения)

0 голосов
/ 03 января 2019

Создание набора данных

myValues = [('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)]
df = sqlContext.createDataFrame(myValues,['card_Scheme','failed','count'])
df.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|
+----------------+------+------+

Метод 1: Этот метод будет медленнее, так как включает в себя трассировку через pivot.

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|
+----------------+------------------+
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...