Найти - Пользователи
Полная версия: вопрос по pySpark 2
Начало » Python для новичков » вопрос по pySpark 2
1
pe1601@mail.ru
приветствую
есть df вида (упрощенно):
 | class | name | sum | year |
-----------------------
| a | abc   | 123 | 1999 |
| a | def   | 125 | 1999 |
| a | ikl   | 127 | 1999 |
| a | mn    | 201 | 2000 |
| a | opr   | 202 | 2000 |

значения в колонка class в данном примере одно - а (в общем случае много…), sum, year - int
надо получить df c максимальным sum по каждому уникальному значению year, т.е. результат должен быть таким:
 | class| 1999 | 2000 |
---------------------
|   a   |  ikl | opr  |

я делаю так (с некоторыми упрощениями и уже полученной подсказкой):

 #размерность по оси Х:
Х=df.select('year').distinct()
#размерность по оси Y (в нашем примере это единственное значение):
Y=df.select('class').distinct()
#создаем df результата:
st=StructField('class', StringType(), True)
schema =StructType().add(st)
for i in X.collect():
  st=StructField(str(i[0]), StringType(), True)
  schema =schema.add(st)
rez=sc.createDataFrame([], schema)
for i0 in Y.collect():
  a=i0[0]   
  sz=[(a)] 
  #накладываем фильтр по class
  df2=df.filter(df.class==a)
  i1=0
  while i1<=X.count()-1:
    year=X.collect()[i1][0]  #текущее значение по Х
    #накладываем фильтр по year
    df3=df2.filter(df2.year==year)
    #далее при помощи метода из библиотеки Pandas:
    pd=df3.toPandas()
    max=pd.loc[pd['sum']==pd['sum'].max()]
    name=max['name'].values[0]
    sz.append(name)
    i1=i1+1
  #Добавляем строку в rez:
  st=sc.createDataFrame(Row(sz), schema)
  rez=rez.unionByName(st)

очевидно двойный цикл с обращением к Pandas внутри крайне не оптимально….

думаю что размерность (Х*Y) результирующего контейнера в любом случае надо получать
отдельно (в общем случае надо предусмотреть сортировку коллекций Х,У по возрастанию, удаление null..)
потом по “очищенным” и отсортированным Х,У формируем результирующий df (пустой)…
а вот его “наполнение” хотелось бы конечно не циклами…

альтернативная тактика: не формировать пустой контейнер, сразу неким образом получить df и уже после этого сортировать и очищать от null, однако есть сомнения что такая тактика даст выигрыш по времени исполнения, но главное нет уверенности в качестве результата… проблема в том, что в общем случае в коллекциях Х,У кроме null могут быть значения “неправильных” типов (например в колонке year - строки), и “вычищать” их из итогового df может оказаться не тривиальной задачей…
ZerG
Правильный подход:
Используй SQL диалект для подобных запросов. Это будет много меньше кода и времени оббработки
Пример по ссылке что давали раньше.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB