【问题标题】:Python's "StandardScaler" and "LabelEncoder", and "fit" and "fit_transform" do not work with a CSV which contains both float and stringPython 的“StandardScaler”和“LabelEncoder”以及“fit”和“fit_transform”不适用于包含浮点数和字符串的 CSV
【发布时间】:2021-05-17 05:15:37
【问题描述】:

我在 Google Colaboratory 学习 MPL 回归器并运行了源代码:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler


scaler = StandardScaler()

data = np.array(table)

scaler.fit(data)
y_index = data.shape[1]-1
sd_x = (scaler.var_[:y_index])**0.5
sd_y = (scaler.var_[y_index])**0.5
mean_x = scaler.mean_[:y_index]
mean_y = scaler.mean_[y_index]


x = (data[:, :y_index]).astype(np.float32)
y = (data[:, y_index]).astype(np.float32)

train_x, test_x, train_y, test_y = train_test_split(x, y, test_size=0.25)
print('Separate training and testing sets!')

它给出了错误ValueError: could not convert string to float: 'Photo Editor & Candy Camera & Grid & ScrapBook'

所以我检查了问题RandomForestClassfier.fit(): ValueError: could not convert string to float。我也试过sklearn-LinearRegression: could not convert string to float: '--'

我从fit(data) 更改为fit_transform(data),但仍然出现同样的错误。然后我从StandardScaler改成了LabelEncoder,从scaler = StandardScaler()改成了scaler = LabelEncoder()。但是出现了不同的错误: ValueError: bad input shape (10841, 13)就行了scaler.fit_transform(data)

您可以在此处查看来自Kaggle's CSV 的 CSV。 CSV 包含不带引号的字符串和数字(​​包含双引号的价格除外)。

【问题讨论】:

    标签: python pandas numpy csv google-colaboratory


    【解决方案1】:

    来自 sklearn 的 LabelEncoder 的文档:这个转换器应该用于编码目标值,即 y,而不是输入 X。

    特别是,它不适合在完整数据集上使用 LabelEncoder

    如果您只想用唯一和数字 ID 替换分类(即字符串值)列的值,一种方法是在您想要的每一列上应用标签编码器(在拆分数据之前)单独编码。当您的示例代码导入pandas 时,我假设您的数据已加载到pandas.DataFrame 之类的

    df = pd.read_csv('/path/to/googleplaystore.csv')
    

    从那里,您可以在每一列上应用编码器:

    df['App'] = LabelEncoder().fit_transform(df['App'].values)
    

    您可能还想看看如何在 pandas 中处理 categorical data

    但是,即使对数据集中的每个非数字列执行此操作,在对编码数据拟合模型之前还有很长的路要走(之后您可能希望将 one-hot encoding 应用于这些列,但这很重要取决于您要使用的型号)。

    【讨论】:

    • 你的意思是scaler['App'] = LabelEncoder().fit_transform(scaler['App'].values)
    • @GustavoReis:不,df 对象是 pandas.DataFrame,您的数据被加载到其中,例如 df = pd.read_csv('/path/to/googleplaystore.csv')。我的建议是,将LabelEncoder 应用于随后包含字符串值的每一列。
    • 它仍然不起作用,因为控制台告诉TypeError: float () argument must be a string or a number, not 'module'。我做了一个样本和小数据集,错误仍然存​​在。也许您可以在 Gist 上检查非常小的代码,看看我的代码是否不正确:here
    • @GustavoReis:我无法重现异常。尽管有些地方可以改进,但您的 Gist 在我这里运行良好。我不清楚你到底想用那段代码归档什么(例如,为什么你分裂y_indices)。请考虑更新您的问题以获得更具体的帮助。
    • 谢谢你,@tobias-windisch。我将删除StandardScaler 并对其进行测试。如果它不起作用,那是我老师的失败。
    【解决方案2】:

    StandardScaler 是 sklearn 的一个预处理类,它接受数字条目并将它们转换为具有 0 均值和单位方差的可能的高斯分布。它不处理文本数据。这就解释了第一个错误。

    LabelEncoder 是 sklearn 的另一个预处理类,它获取数据并将它们映射到数字编码表示。 例如:["apple","banana","apple","banana"] 到 [0,1,0,1]

    您的数据集有缺失值,您应该先处理它们。通过插补、删除或其他类似方法。

    然后你应该转换每列的类型(除了评级之外的所有类型都被认为是对象或字符串)以正确处理每种数据类型。

    table = pd.read_csv('googleplaystore.csv')
    # check dataset info
    table.info()
    # check missing values
    table.isna().sum()
    

    【讨论】:

    • 我自己创建了一个简单的 3 行 CSV 数据库,它给出了同样的错误。我使用 Google Colaboratory 的另一个仅包含数字的简单数据库进行了测试,它确实有效。我知道源代码与包含字符串的数据库不兼容。但我不知道转换。我只是在学习。
    【解决方案3】:

    说实话,我认为这更像是一个概念问题,而不是技术问题。正如其他用户告诉您的那样,StandarScaler 必须用于数字列,但您的大多数数据框列都是 object 类型。可能你应该在上面使用OneHotEncoder,sklearn 上的所有转换器都有类似的行为。

    from sklearn.preprocessing import OneHotEncoder
    ohe = OneHotEncoder(handle_unknown='ignore')
    ohe.fit_transform(X)  # your data without target column
    # ...blabla...
    

    最后,我建议你阅读 sklearn 中的 Pipelines,我认为它们比很多乱七八糟的代码更优雅。您可以将预处理和建模步骤放在同一管道上,例如 here

    【讨论】:

    • 我使用 Jupyter Notebook,但不幸的是 Jupyter 报错:AttributeError: 'OneHotEncoder' object has no attribute 'var_' 也许你应该检查here 并查看我的代码。您确实需要重现异常。
    猜你喜欢
    • 2020-05-25
    • 2016-11-26
    • 2014-10-13
    • 2020-08-11
    • 2015-10-31
    • 2021-08-02
    • 2021-03-05
    • 1970-01-01
    • 2013-02-27
    相关资源
    最近更新 更多