Как применить groupby и транспонировать в Pyspark?

У меня есть фрейм данных, как показано ниже

df = pd.DataFrame({
'subject_id':[1,1,1,1,2,2,2,2,3,3,4,4,4,4,4],
 'readings' : ['READ_1','READ_2','READ_1','READ_3','READ_1','READ_5','READ_6','READ_8','READ_10','READ_12','READ_11','READ_14','READ_09','READ_08','READ_07'],
 'val' :[5,6,7,11,5,7,16,12,13,56,32,13,45,43,46], 
 })

Мой вышеупомянутый входной фреймворк выглядит так

введите здесь описание изображения

Хотя приведенный ниже код отлично работает (спасибо Jezrael) в Python pandas, когда я применяю его к реальным данным (более 4M записей), он работает в течение длительного времени. Итак, я пытался использовать pyspark. Обратите внимание, я уже пробовал _3 _, _ 4 _, _ 5_, которые эквивалентны пандам для крупномасштабной обработки, но тоже не помогли. Приведенные ниже коды делают it generates the summary statistics for each subject for each reading. Вы можете взглянуть на ожидаемый результат ниже, чтобы получить представление

df_op = (df.groupby(['subject_id','readings'])['val']
        .describe()
        .unstack()
        .swaplevel(0,1,axis=1)
        .reindex(df['readings'].unique(), axis=1, level=0))
df_op.columns = df_op.columns.map('_'.join)
df_op = df_op.reset_index()

Можете ли вы помочь мне выполнить описанную выше операцию в pyspark? Когда я попробовал следующее, он выдал ошибку

df.groupby(['subject_id','readings'])['val'] 

Например, subject_id = 1 имеет 4 чтения, но 3 уникальных чтения. Таким образом, мы получаем 3 * 8 = 24 столбца для subject_id = 1. Почему 8? Потому что это MIN,MAX,COUNT,Std,MEAN,25%percentile,50th percentile,75th percentile. Надеюсь это поможет

Когда я начал с этого в pyspark, он возвращает ошибку ниже

TypeError: объект GroupedData не подлежит подписке

Я ожидаю, что мой результат будет таким, как показано ниже

введите здесь описание изображения


person The Great    schedule 22.10.2019    source источник
comment
Что именно вы хотите делать? Код не является хорошей ссылкой, так как он не работает.   -  person pissall    schedule 22.10.2019
comment
@pissall - Нет, это рабочий код. можешь попробовать еще раз? Я бы хотел получить summary statistics for each subject for each reading   -  person The Great    schedule 22.10.2019
comment
@pissall - Обновлен примером для subject_id = 1 в сообщении. Дайте мне знать, если у вас возникнут еще какие-либо сомнения   -  person The Great    schedule 22.10.2019
comment
Какую сводную статистику вы хотите получить? Вам нужно будет кодировать агрегат с помощью groupby   -  person pissall    schedule 22.10.2019
comment
Вроде Min,Max,Avg,Count,25th percentile, 75th percentile. Как видите, я смог сделать это в пандах, но не в pyspark. Вы можете мне помочь?   -  person The Great    schedule 22.10.2019
comment
Я уже пробовал groupby. Если вы увидите мою попытку pyspark в приведенном выше коде, вы увидите, что у меня есть ошибка. Мне просто нравится воспроизводить тот же код pandas в pyspark   -  person The Great    schedule 22.10.2019
comment
Я решу это за тебя   -  person pissall    schedule 22.10.2019


Ответы (1)


Вам нужно сначала сгруппировать и получить статистику для каждого показания, а затем сделать поворот, чтобы получить ожидаемый результат.

import pyspark.sql.functions as F

agg_df = df.groupby("subject_id", "readings").agg(F.mean(F.col("val")), F.min(F.col("val")), F.max(F.col("val")),
                                                    F.count(F.col("val")),
                                                    F.expr('percentile_approx(val, 0.25)').alias("quantile_25"),
                                                    F.expr('percentile_approx(val, 0.75)').alias("quantile_75"))

Это даст вам следующий результат:

+----------+--------+--------+--------+--------+----------+-----------+-----------+
|subject_id|readings|avg(val)|min(val)|max(val)|count(val)|quantile_25|quantile_75|
+----------+--------+--------+--------+--------+----------+-----------+-----------+
|         2|  READ_1|     5.0|       5|       5|         1|          5|          5|
|         2|  READ_5|     7.0|       7|       7|         1|          7|          7|
|         2|  READ_8|    12.0|      12|      12|         1|         12|         12|
|         4| READ_08|    43.0|      43|      43|         1|         43|         43|
|         1|  READ_2|     6.0|       6|       6|         1|          6|          6|
|         1|  READ_1|     6.0|       5|       7|         2|          5|          7|
|         2|  READ_6|    16.0|      16|      16|         1|         16|         16|
|         1|  READ_3|    11.0|      11|      11|         1|         11|         11|
|         4| READ_11|    32.0|      32|      32|         1|         32|         32|
|         3| READ_10|    13.0|      13|      13|         1|         13|         13|
|         3| READ_12|    56.0|      56|      56|         1|         56|         56|
|         4| READ_14|    13.0|      13|      13|         1|         13|         13|
|         4| READ_07|    46.0|      46|      46|         1|         46|         46|
|         4| READ_09|    45.0|      45|      45|         1|         45|         45|
+----------+--------+--------+--------+--------+----------+-----------+-----------+

Используя groupby subject_id при повороте readings, вы получите ожидаемый результат:

agg_df2 = df.groupby("subject_id").pivot("readings").agg(F.mean(F.col("val")), F.min(F.col("val")), F.max(F.col("val")),
                                                         F.count(F.col("val")),
                                                         F.expr('percentile_approx(val, 0.25)').alias("quantile_25"),
                                                         F.expr('percentile_approx(val, 0.75)').alias("quantile_75"))

for i in agg_df2.columns:
    agg_df2 = agg_df2.withColumnRenamed(i, i.replace("(val)", ""))
agg_df2.show()

+----------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+---------------+---------------+---------------+-----------------+------------------+------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+
|subject_id|READ_07_avg(val)|READ_07_min(val)|READ_07_max(val)|READ_07_count(val)|READ_07_quantile_25|READ_07_quantile_75|READ_08_avg(val)|READ_08_min(val)|READ_08_max(val)|READ_08_count(val)|READ_08_quantile_25|READ_08_quantile_75|READ_09_avg(val)|READ_09_min(val)|READ_09_max(val)|READ_09_count(val)|READ_09_quantile_25|READ_09_quantile_75|READ_1_avg(val)|READ_1_min(val)|READ_1_max(val)|READ_1_count(val)|READ_1_quantile_25|READ_1_quantile_75|READ_10_avg(val)|READ_10_min(val)|READ_10_max(val)|READ_10_count(val)|READ_10_quantile_25|READ_10_quantile_75|READ_11_avg(val)|READ_11_min(val)|READ_11_max(val)|READ_11_count(val)|READ_11_quantile_25|READ_11_quantile_75|READ_12_avg(val)|READ_12_min(val)|READ_12_max(val)|READ_12_count(val)|READ_12_quantile_25|READ_12_quantile_75|READ_14_avg(val)|READ_14_min(val)|READ_14_max(val)|READ_14_count(val)|READ_14_quantile_25|READ_14_quantile_75|READ_2_avg(val)|READ_2_min(val)|READ_2_max(val)|READ_2_count(val)|READ_2_quantile_25|READ_2_quantile_75|READ_3_avg(val)|READ_3_min(val)|READ_3_max(val)|READ_3_count(val)|READ_3_quantile_25|READ_3_quantile_75|READ_5_avg(val)|READ_5_min(val)|READ_5_max(val)|READ_5_count(val)|READ_5_quantile_25|READ_5_quantile_75|READ_6_avg(val)|READ_6_min(val)|READ_6_max(val)|READ_6_count(val)|READ_6_quantile_25|READ_6_quantile_75|READ_8_avg(val)|READ_8_min(val)|READ_8_max(val)|READ_8_count(val)|READ_8_quantile_25|READ_8_quantile_75|
+----------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+---------------+---------------+---------------+-----------------+------------------+------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+
|         1|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|            6.0|              5|              7|                2|                 5|                 7|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|            6.0|              6|              6|                1|                 6|                 6|           11.0|             11|             11|                1|                11|                11|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|
|         3|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|           null|           null|           null|             null|              null|              null|            13.0|              13|              13|                 1|                 13|                 13|            null|            null|            null|              null|               null|               null|            56.0|              56|              56|                 1|                 56|                 56|            null|            null|            null|              null|               null|               null|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|
|         2|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|            5.0|              5|              5|                1|                 5|                 5|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|            null|            null|            null|              null|               null|               null|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|            7.0|              7|              7|                1|                 7|                 7|           16.0|             16|             16|                1|                16|                16|           12.0|             12|             12|                1|                12|                12|
|         4|            46.0|              46|              46|                 1|                 46|                 46|            43.0|              43|              43|                 1|                 43|                 43|            45.0|              45|              45|                 1|                 45|                 45|           null|           null|           null|             null|              null|              null|            null|            null|            null|              null|               null|               null|            32.0|              32|              32|                 1|                 32|                 32|            null|            null|            null|              null|               null|               null|            13.0|              13|              13|                 1|                 13|                 13|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|           null|           null|           null|             null|              null|              null|
+----------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+---------------+---------------+---------------+-----------------+------------------+------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+----------------+----------------+----------------+------------------+-------------------+-------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+---------------+---------------+---------------+-----------------+------------------+------------------+


person pissall    schedule 22.10.2019
comment
Просто используй второй шаг, братан. Первый шаг - демонстрация того, как получить статистику. - person pissall; 22.10.2019
comment
Ах, да. Только что заметил имя фрейма данных - person The Great; 22.10.2019
comment
На самом деле я пытаюсь просмотреть вывод с помощью agg_df2.show(). Невозможно проверить вывод show из-за нулевых значений из-за моих реальных данных. Можно ли просмотреть это в красивой форме таблицы, такой как фрейм данных pandas? Я пробовал это result_pdf = agg_df2.select("*").toPandas(), но он работает уже давно. - person The Great; 22.10.2019
comment
И это в конечном итоге привело к ошибке. Я имею ввиду дисплей. Может быть, из-за большого набора данных? Как я могу увидеть результат в виде таблицы, как показано в разделе ожидаемых результатов? - person The Great; 22.10.2019
comment
Да, toPandas() для большого набора данных очень дорого, потому что он перенесет все ваши данные на исполнителя. Проверьте память исполнителя на то же самое. - person pissall; 22.10.2019
comment
Спасибо. Есть ли другой способ посмотреть на это? - person The Great; 22.10.2019
comment
@SSMK Более эффективный способ сохранить это - без pivot. Как на первом этапе. Это будет легче визуализировать. Если у вас есть столбцы для всех показаний, вы излишне увеличиваете потребление памяти. Так много столбцов и так много нулевых значений. - person pissall; 22.10.2019
comment
Позвольте нам продолжить это обсуждение в чате. - person The Great; 22.10.2019