Преобразование плотного вектора в датафрейм с помощью Pyspark

1

Сначала я попробовал все в ссылке ниже, чтобы исправить мою ошибку, но никто из них не работал.

Как преобразовать RDD плотного вектора в DataFrame в pyspark?

Я пытаюсь преобразовать плотный вектор в кадр данных (желательно Spark) вместе с именами столбцов и проблемами.

Моя колонка в искровом информационном кадре - это вектор, который был создан с помощью Vector Assembler, и теперь я хочу преобразовать его обратно в фреймворк данных, поскольку я хотел бы создавать графики для некоторых переменных в векторе.

Подход 1:

from pyspark.ml.linalg import SparseVector, DenseVector
from pyspark.ml.linalg import Vectors

temp=output.select("all_features")
temp.rdd.map(
    lambda row: (DenseVector(row[0].toArray()))
).toDF()

Ниже приведена ошибка

TypeError: not supported type: <type 'numpy.ndarray'>

Подход 2:

from pyspark.ml.linalg import VectorUDT
from pyspark.sql.functions import udf
from pyspark.ml.linalg import *

as_ml = udf(lambda v: v.asML() if v is not None else None, VectorUDT())
result = output.withColumn("all_features", as_ml("all_features"))
result.head(5)

Ошибка:

AttributeError: 'numpy.ndarray' object has no attribute 'asML'

Я также попытался преобразовать dataframe в кадр данных Pandas, и после этого я не могу разделить значения на отдельные столбцы

Подход 3:

pandas_df=temp.toPandas()
pandas_df1=pd.DataFrame(pandas_df.all_features.values.tolist())

Выше кода работает нормально, но у меня все еще есть только один столбец в моем фреймворке данных со всеми значениями, разделенными запятыми в виде списка.

Любая помощь очень ценится!

РЕДАКТИРОВАТЬ:

Вот как выглядит мой временный фрейм. Он имеет только один столбец all_features. Я пытаюсь создать dataframe, который разбивает все эти значения на отдельные столбцы (all_features - это вектор, который был создан с использованием 200 столбцов)

+--------------------+
|        all_features|
+--------------------+
|[0.01193689934723...|
|[0.04774759738895...|
|[0.0,0.0,0.194417...|
|[0.02387379869447...|
|[1.89796699621085...|
+--------------------+
only showing top 5 rows

Ожидаемый результат - это кадр данных со всеми 200 столбцами, выделенными в фрейме данных

+----------------------------+
|        col1| col2| col3|...
+----------------------------+
|0.01193689934723|0.0|0.5049431301173817...
|0.04774759738895|0.0|0.1657316216149636...
|0.0|0.0|7.213126372469...
|0.02387379869447|0.0|0.1866693496827619|...
|1.89796699621085|0.0|0.3192169213385746|...
+----------------------------+
only showing top 5 rows

Вот как выглядит мой вывод Pandas DF

              0
0   [0.011936899347238104, 0.0, 0.5049431301173817...
1   [0.047747597388952415, 0.0, 0.1657316216149636...
2   [0.0, 0.0, 0.19441761495525278, 7.213126372469...
3   [0.023873798694476207, 0.0, 0.1866693496827619...
4   [1.8979669962108585, 0.0, 0.3192169213385746, ...
  • 1
    Можете ли вы сказать нам явно, какой у вас ввод, какой вы хотите, и какой вы получаете сейчас? Это помогает нам лучше понять вашу проблему (и быстрее). Обычно требуется минимальный воспроизводимый пример . Например, я не уверен, какие значения у вас есть в вашем столбце "all_features", и поэтому я не могу точно знать, что приводит к использованию .values.tolist()
  • 0
    Вы пробовали rdd.map(lambda x: (x, )).toDF( ) как указано в указанной вами ссылке? Это обычно работает.
Показать ещё 4 комментария
Теги:
pandas
dataframe
apache-spark

1 ответ

1
Лучший ответ

Поскольку вам нужны все функции в отдельных столбцах (как я получил от вашего EDIT), ссылка на предоставленный вами ответ не является вашим решением.

Попробуй это,

#column_names
temp = temp.rdd.map(lambda x:[float(y) for y in x['all_features']]).toDF(column_names)

РЕДАКТИРОВАТЬ:

Поскольку ваш temp изначально является фреймворком данных, вы также можете использовать этот метод, не преобразовывая его в rdd,

import pyspark.sql.functions as F
from pyspark.sql.types import *

splits = [F.udf(lambda val: float(val[i].item()),FloatType()) for i in range(200)]
temp = temp.select(*[s(F.col('all_features')).alias(c) for c,s in zip(column_names,splits)])
temp.show()
  • 0
    Спасибо, Майянк! Опробовал ваше первое решение, и оно отлично сработало! Есть ли способ, которым я могу назначить имена столбцов для вновь созданного кадра данных, используя список имен столбцов, которые у меня уже есть?
  • 0
    В самом деле, вы можете. Проверьте мой ответ сейчас. Кроме того, если вы нашли мой ответ полезным, сделайте upvote и отметьте как принятый :)
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню