Pyspark конвертирует числовые данные в категорию без значения reindex [duplicate]

Это происходит потому, что ваш локальный модуль с именем requests.py скрывает установленный модуль requests, который вы пытаетесь использовать. Текущая директория добавляется к sys.path, поэтому локальное имя имеет приоритет над установленным именем.

Дополнительная подсказка для отладки, когда это возникает, - это внимательно изучить Трейсбек и понять, что имя ваш скрипт соответствует вашему модулю, который вы пытаетесь импортировать:

Обратите внимание на имя, которое вы использовали в своем скрипте:

File "/Users/me/dev/rough/requests.py", line 1, in <module>

Модуль, который вы пытаетесь импортировать: requests

Переименуйте свой модуль во что-то еще, чтобы избежать столкновения имен.

Python может сгенерировать файл requests.pyc рядом с вашим файлом requests.py (в каталоге __pycache__ в Python 3). Удалите это также после переименования, поскольку интерпретатор все равно будет ссылаться на этот файл, повторно создавая ошибку. Однако файл pyc в __pycache__ должен не влиять на ваш код, если файл py удален.

В этом примере переименование файла на my_requests.py, удалив requests.pyc и снова выполнив успешную печать <Response [200]>.

4
задан zero323 28 May 2016 в 10:38
поделиться

2 ответа

Я бы предпочел избежать хлопот кодирования и декодирования,

Вы не можете полностью избежать этого. Необходимые метаданные для категориальной переменной на самом деле являются отображением между значением и индексом. Тем не менее, нет необходимости делать это вручную или создавать настраиваемый трансформатор . Предположим, что у вас есть такой кадр данных:

import numpy as np
import pandas as pd

df = sqlContext.createDataFrame(pd.DataFrame({
    "x1": np.random.random(1000),
    "x2": np.random.choice(3, 1000),
    "x4": np.random.choice(5, 1000)
}))

Все, что вам нужно, это ассемблер и индекс:

from pyspark.ml.feature import VectorAssembler, VectorIndexer
from pyspark.ml import Pipeline

pipeline = Pipeline(stages=[
    VectorAssembler(inputCols=df.columns, outputCol="features_raw"),
    VectorIndexer(
        inputCol="features_raw", outputCol="features", maxCategories=10)])

transformed = pipeline.fit(df).transform(df)
transformed.schema.fields[-1].metadata

## {'ml_attr': {'attrs': {'nominal': [{'idx': 1,
##      'name': 'x2',
##      'ord': False,
##      'vals': ['0.0', '1.0', '2.0']},
##     {'idx': 2,
##      'name': 'x4',
##      'ord': False,
##      'vals': ['0.0', '1.0', '2.0', '3.0', '4.0']}],
##    'numeric': [{'idx': 0, 'name': 'x1'}]},
##   'num_attrs': 3}}

В этом примере также показана информация о типе, которую вы предоставляете, чтобы отметить данный элемент вектора как категориальная переменная

{
    'idx': 2,  # Index (position in vector)
    'name': 'x4',  # name
    'ord': False,  # is ordinal?
    # Mapping between value and label
    'vals': ['0.0', '1.0', '2.0', '3.0', '4.0']  
}

Итак, если вы хотите построить это с нуля, все, что вам нужно сделать, это правильная схема:

from pyspark.sql.types import *
from pyspark.mllib.linalg import VectorUDT

# Lets assume we have only a vector
raw = transformed.select("features_raw")

# Dictionary equivalent to transformed.schema.fields[-1].metadata shown abov
meta = ... 
schema = StructType([StructField("features", VectorUDT(), metadata=meta)])

sqlContext.createDataFrame(raw.rdd, schema)

Но это довольно неэффективно из-за требуемой сериализации, десериализации.

Начиная с Spark 2.2 вы также можете использовать аргумент метаданных:

df.withColumn("features", col("features").alias("features", metadata=meta))

См. также Приложить метаданные к столбцу вектора в Spark

2
ответ дан zero323 19 August 2018 в 00:15
поделиться

Hey zero323 Я использовал ту же технику для просмотра метаданных, и я закодировал это Transformer.

def _transform(self, data):
    maxValues = self.getOrDefault(self.maxValues)
    categoricalCols = self.getOrDefault(self.categoricalCols)

    new_schema = types.StructType(data.schema.fields)
    new_data = data
    for (col, maxVal) in zip(categoricalCols, maxValues):
        # I have not decided if I should make a new column or
        # overwrite the original column
        new_col_name = col + "_categorical"

        new_data = new_data.withColumn(new_col_name,
                                       data[col].astype(types.DoubleType()))

        # metadata for a categorical column                                                                                                                                 
        meta = {u'ml_attr' : {u'vals' : [unicode(i) for i in range(maxVal + 1)],
                              u'type' : u'nominal',
                              u'name' : new_col_name}}

        new_schema.add(new_col_name, types.DoubleType(), True, meta)

    return data.sql_ctx.createDataFrame(new_data.rdd, new_schema)
0
ответ дан unda91 19 August 2018 в 00:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: