#pyspark #pivot
#pyspark #сводная
Вопрос:
У меня есть pypark df вот так:
------- ------- ----------- ----------- ----------- ----------- ----------- -----------
| SEQ_ID|TOOL_ID|kurtosis_1m|kurtosis_2m|kurtosis_3m|kurtosis_4m|kurtosis_5m|kurtosis_6m|
------- ------- ----------- ----------- ----------- ----------- ----------- -----------
|3688539| 99725| 6.7484| 6.2753| 6.2055| 7.2076| 7.0501| 7.5099|
|3689076| 99705| 4.8109| 4.3774| 4.1131| 4.4084| 4.1568| 4.4445|
------- ------- ----------- ----------- ----------- ----------- ----------- -----------
Мне нужно повернуть его таким образом, чтобы в итоге получился фрейм данных следующим образом:
------- ------- -----------
| SEQ_ID|TOOL_ID|kurtosis |
------- ------- -----------
|3688539| 99725| 6.7484|
|3688539| 99725| 6.2753|
|3688539| 99725| 6.2055|
|3688539| 99725| 7.2076|
|3688539| 99725| 7.0501|
|3688539| 99725| 7.5099|
|3689076| 99705| 4.8109|
|3689076| 99705| 4.3774|
|3689076| 99705| 4.1131|
|3689076| 99705| 4.4084|
|3689076| 99705| 4.1568|
|3689076| 99705| 4.4445|
------- ------- -----------
Я подумал, что одним из способов было бы создать kurtosis
столбец как столбец массива, а затем развернуть его. Как объединить значения столбцов в фрейме данных в один столбец в виде массива.
У меня есть другие столбцы, такие как mean_1m
, mean_2m
и т.д. … которые мне нужно повернуть таким же образом.
Есть идеи?
Спасибо
Ответ №1:
Вы можете создать массив фреймов данных и объединить их.
Сначала определите kurtosis
столбцы:
sub_string = "kurtosis"
kurtosis_col = [x for x in df.schema.names if sub_string in x]
Теперь создайте массив фреймов данных, равный количеству kurtosis
столбцов:
from functools import reduce
from pyspark.sql import DataFrame
from pyspark.sql.functions import col
df_array = [df.withColumn('col', F.concat(F.col(x)))
.select('seq_id', 'tool_id', 'col') for x in kurtosis_col]
# Union them
reduce(DataFrame.unionAll, df_array).withColumnRenamed("col", "kurtosis").show()
Вывод:
------- ------- --------
| seq_id|tool_id|kurtosis|
------- ------- --------
|3688539| 99725| 6.7484|
|3688539| 99725| 7.2076|
|3688539| 99725| 6.2753|
|3688539| 99725| 6.2055|
|3688539| 99725| 7.5099|
|3688539| 99725| 7.0501|
|3689076| 99705| 4.4084|
|3689076| 99705| 4.1131|
|3689076| 99705| 4.8109|
|3689076| 99705| 4.4445|
|3689076| 99705| 4.3774|
|3689076| 99705| 4.1568|
------- ------- --------
Вы можете следовать аналогичному подходу для других установленных столбцов, таких как mean_1m
, и т.д. Один из способов объединить их обратно и избежать дублирования — использовать row_number()
и monotonically_increasing_id()
перед объединением. Дайте мне знать, если вам нужен этот фрагмент кода.
Комментарии:
1. Я думаю, что использование встроенной
array
функции pyspark может быть проще. Спасибо за ваше решение, Cena. Я действительно ценю это!
Ответ №2:
Вы можете использовать array для объединения нескольких столбцов в один массив, а затем — как вы уже описали в своем вопросе — разбить массив.
from pyspark.sql import functions as F
cols = [x for x in df.schema.names if "kurtosis" in x]
df.withColumn("kurtosis", F.explode(F.array(cols)))
.drop(*cols)
.show()
Вывод:
------- ------- --------
| SEQ_ID|TOOL_ID|kurtosis|
------- ------- --------
|3688539| 99725| 6.7484|
|3688539| 99725| 6.2753|
|3688539| 99725| 6.2055|
|3688539| 99725| 7.2076|
|3688539| 99725| 7.0501|
|3688539| 99725| 7.5099|
|3689076| 99705| 4.8109|
|3689076| 99705| 4.3774|
|3689076| 99705| 4.1131|
|3689076| 99705| 4.4084|
|3689076| 99705| 4.1568|
|3689076| 99705| 4.4445|
------- ------- --------
Комментарии:
1.
if string in x
подбирает все слова с буквами. Как мне заставить его выбрать точное слово? Напримерif 'UL' in x
, выбирает столбцы с именамиUL
, иMUL
я хочу, чтобы он выбирал толькоUL
2. @thentangler замените
in
на a==
, как вы бы сделали в обычном условии if. Некоторые примеры можно найти здесь