Массив строк Pyspark с динамической длиной в столбце данных в единичном кодировании - PullRequest
0 голосов
/ 19 сентября 2019

Я хотел бы преобразовать столбец, который содержит строки, такие как:

 ["ABC","def","ghi"] 
 ["Jkl","ABC","def"]
 ["Xyz","ABC"]

В закодированный столбец, как это:

 [1,1,1,0,0]
 [1,1,0,1,0]
 [0,1,0,0,1]

Есть ли класс для этого в pyspark.ml.feature?

Редактировать: В закодированном столбце первая запись всегда соответствует значению "ABC" и т. д. 1 означает, что присутствует "ABC", а 0 означает, что его нет в соответствующей строке.

Ответы [ 2 ]

2 голосов
/ 19 сентября 2019

Вам нужно будет расширить список в одном столбце до нескольких столбцов n (где n - количество элементов в данном списке).Затем вы можете использовать класс OneHotEncoderEstimator , чтобы преобразовать его в One горячо закодированных объектов.

Пожалуйста, следуйте примеру в документации:

from pyspark.ml.feature import OneHotEncoderEstimator

df = spark.createDataFrame([
    (0.0, 1.0),
    (1.0, 0.0),
    (2.0, 1.0),
    (0.0, 2.0),
    (0.0, 1.0),
    (2.0, 0.0)
], ["categoryIndex1", "categoryIndex2"])

encoder = OneHotEncoderEstimator(inputCols=["categoryIndex1", "categoryIndex2"],
                                 outputCols=["categoryVec1", "categoryVec2"])
model = encoder.fit(df)
encoded = model.transform(df)
encoded.show()

Класс OneHotEncoder устарел с v2.3, потому что это преобразователь без состояния, он не может использоваться нановые данные, где количество категорий может отличаться от данных обучения.

Это поможет вам разбить список: Как разбить список на несколько столбцов в Pyspark?

1 голос
/ 19 сентября 2019

Возможно, вы можете использовать CountVectorizer , ниже приведен пример:

Обновление: удален шаг для удаления дубликатов в массивах, вы можете установить binary=True, когданастройка CountVectorizer:

from pyspark.ml.feature import CountVectorizer
from pyspark.sql.functions import udf, col

df = spark.createDataFrame([
        (["ABC","def","ghi"],)
      , (["Jkl","ABC","def"],)
      , (["Xyz","ABC"],)
    ], ['arr']
)

создать модель CountVectorizer:

cv = CountVectorizer(inputCol='arr', outputCol='c1', binary=True)

model = cv.fit(df)

vocabulary = model.vocabulary
# [u'ABC', u'def', u'Xyz', u'ghi', u'Jkl']

Создать UDF для преобразования вектора в массив

udf_to_array = udf(lambda v: v.toArray().tolist(), 'array<double>')

Получить вектор и проверитьсодержание:

df1 = model.transform(df)

df1.withColumn('c2', udf_to_array('c1')) \
   .select('*', *[ col('c2')[i].astype('int').alias(vocabulary[i]) for i in range(len(vocabulary))]) \
   .show(3,0)
+---------------+-------------------------+-------------------------+---+---+---+---+---+
|arr            |c1                       |c2                       |ABC|def|Xyz|ghi|Jkl|
+---------------+-------------------------+-------------------------+---+---+---+---+---+
|[ABC, def, ghi]|(5,[0,1,3],[1.0,1.0,1.0])|[1.0, 1.0, 0.0, 1.0, 0.0]|1  |1  |0  |1  |0  |
|[Jkl, ABC, def]|(5,[0,1,4],[1.0,1.0,1.0])|[1.0, 1.0, 0.0, 0.0, 1.0]|1  |1  |0  |0  |1  |
|[Xyz, ABC]     |(5,[0,2],[1.0,1.0])      |[1.0, 0.0, 1.0, 0.0, 0.0]|1  |0  |1  |0  |0  |
+---------------+-------------------------+-------------------------+---+---+---+---+---+
...