IllegalArgumentException: столбец должен иметь тип struct но на самом деле был двойной. - PullRequest
1 голос
/ 06 апреля 2020

У меня есть датафрейм с несколькими категориальными столбцами. Я пытаюсь найти статистику по квадратам, используя встроенную функцию между двумя столбцами:

from pyspark.ml.stat import ChiSquareTest

r = ChiSquareTest.test(df, 'feature1', 'feature2')

Однако, это дает мне ошибку:

IllegalArgumentException: 'requirement failed: Column feature1 must be of type struct<type:tinyint,size:int,indices:array<int>,values:array<double>> but was actually double.'

Тип данных для feature1 is:

feature1: double (nullable = true)

Не могли бы вы помочь мне в этом вопросе?

Ответы [ 2 ]

2 голосов
/ 06 апреля 2020

Чтобы расширить ответ Оли, Spark ML ожидает, что функции будут храниться в случаях pyspark.ml.linalg.Vector. Существует два вида векторов:

  • плотные векторы - это просто массивы, которые содержат все элементы вектора, включая все нули, и представлены в виде массива Spark array<T>
  • разреженных векторов - это более сложные структуры данных, в которых хранятся ненулевые элементы вектора, что позволяет компактно хранить огромные векторы с небольшим количеством ненулевых элементов. Разреженные векторы имеют три компонента:
    • целое число size, которое указывает полное измерение вектора
    • массива indices, который содержит позиции ненулевых элементов
    • a values массив, который содержит значения ненулевых элементов

Оба типа вектора фактически представлены с использованием структуры для разреженных векторов, тогда как для плотных векторов Массив indices не используется, а values хранит все значения. Первый элемент структуры, type, используется для различения guish между двумя типами.

Итак, если вы видите ошибку, что что-то ожидает struct<type:tinyint,size:int,indices:array<int>,values:array<double>>, это означает, что вы должны передать экземпляры pyspark.ml.linagl.Vector, а не просто числа.

Чтобы получить Vector s, вы можете использовать pyspark.ml.feature.VectorAssembler, чтобы собрать один или несколько независимых столбцов объектов в один векторный столбец, или создать вручную они используют фабричные методы Vectors.dense() (для плотных векторов) и Vectors.sparse() (для разреженных векторов) фабричного объекта pyspark.ml.linalg.Vectors. Использование VectorAssembler, вероятно, проще и быстрее, поскольку оно реализовано в Scala. Для использования явного создания вектора обратитесь к примеру для ChiSquareTest в документации PySpark.

2 голосов
/ 06 апреля 2020

spark-ml не является типичной статистической библиотекой. Это очень ML ориентированный. Поэтому предполагается, что вы захотите запустить тест между меткой и элементом или группой элементов.

Следовательно, аналогично тому, как при обучении модели вам необходимо собрать элементы, с которыми вы хотите протестировать

В вашем случае вы можете просто собрать feature1 следующим образом:

from pyspark.ml.stat import ChiSquareTest
from pyspark.ml.feature import VectorAssembler

data = [(1, 2), (3, 4), (2, 1), (4, 3)]
df = spark.createDataFrame(data, ['feature1', 'feature2'])
assembler = VectorAssembler().setInputCols(['feature1']).setOutputCol('features')

ChiSquareTest.test(assembler.transform(df), 'features', 'feature2').show(false)

На всякий случай код в scala:

import org.apache.spark.ml.stat.ChiSquareTest
import org.apache.spark.ml.feature.VectorAssembler

val df = Seq((1, 2, 3), (1, 2, 3), (4, 5, 6), (6, 5, 4))
    .toDF("feature1, "feature2", "feature3")
val assembler = new VectorAssembler()
    .setInputCols(Array("feature1"))
    .setOutputCol("features")

ChiSquareTest.test(assembler.transform(df), "features", "feature2").show(false)
...