微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

数据帧的列正在交换:为什么在按名称标识和分配列时循环为什么切换列值? 带有我的本地文件的上传副本:使用笔记本版本1中的原始AmesHousing.csv:我使用的导致Kaggle笔记本电脑发生列交换的数据集

如何解决数据帧的列正在交换:为什么在按名称标识和分配列时循环为什么切换列值? 带有我的本地文件的上传副本:使用笔记本版本1中的原始AmesHousing.csv:我使用的导致Kaggle笔记本电脑发生列交换的数据集

我需要我将在下面粘贴的特定代码的帮助。我正在使用Dean De Cock收集的Ames住房数据集。 我正在使用Python笔记本并通过Anaconda的Jupyter Lab 2.1.5进行编辑。 以下代码应该替换所有np.nan或“ None”值。由于某些原因, 在for循环中反复调用一个手工函数后,结果数据帧的列将被交换。

注意:我知道我可以使用“计算机”来完成此操作。我计划选择数字和对象类型的特征,分别进行插补,然后重新组合在一起。附带说明一下,我可以通过显示或验证文本来手动输出详细信息吗?

在相关单元格中,流程为:

  1. 获取并分配数据帧df_train中的数据点数。
  2. 获取并分配一个序列,该序列列出df_train中的空值计数。语法为sr_null_counts = df_train.isnull().sum()
  3. 创建一个空列表,其值的5%等于空的要素名称将附加到该列表中。他们稍后会被丢弃 在for循环之外。起初我以为这是问题所在,因为命令就地放置了df_train的列 曾经在for循环中。
  4. 反复调用一个手工函数来填充空值不超过df_train行数5%的列。

我使用了一个具有for循环和嵌套try-except语句的函数

  1. 接受序列,如果序列是数据帧中的列,则接受该序列的名称(可选)。它分配通过的系列的副本 到局部变量。
  2. 按照确切的顺序,(a)尝试用传递的序列的平均值替换所有空值(NaNNone)。 (b)如果失败,请尝试将所有空值替换为该序列的中位数。 (c)如果仍然失败,则将所有空值替换为该系列的模式。
  3. 返回已替换为所有空值的系列的编辑副本。它还应该打印出告诉我什么功能的字符串 进行了修改,并使用汇总统计信息替换/估算缺失值。

最后一行是删除所有标记为缺失值超过5%的列。

这是完整的代码

将主数据框拆分为训练和测试集。

已通过df_housing = pd.read_csv(sep = '\t',filepath_or_buffer = "AmesHousing.tsv")加载了完整的数据集。

def make_traintest(df,train_fraction = 0.7,random_state_val = 88):
    df = df.copy()
    df_train = df.sample(frac = train_fraction,random_state = random_state_val)    
    bmask_istrain = df.index.isin(df_train.index.values)
    df_test = df.loc[ ~bmask_istrain ]
    
    return {
        "train":df_train,"test":df_test
        }

dict_traintest = make_traintest(df = df_housing)
df_train = dict_traintest["train"]
df_test = dict_traintest["test"]

获取具有空值的列的列表

lst_have_nulls = []
for feature in df_housing.columns.values.tolist():
    nullcount = df_housing[feature].isnull().sum()
    if nullcount > 0:
        lst_have_nulls.append(feature)
        print(feature,"\n=====\nNull Count:\t",nullcount,'\n',df_housing[feature].value_counts(dropna = False),'\n*****')

手工功能的定义:

def impute_series(sr_values,feature_name = ''):
    sr_out = sr_values.copy()
    try:        
        sr_out.fillna(value = sr_values.mean())
        print("Feature",feature_name,"imputed with mean:",sr_values.mean())
    except Exception as e:
        print("Filling NaN values with mean of feature","caused an error:\n",e)
        try:
            sr_out.fillna(value = sr_values.median())
            print("Feature","imputed with median:",sr_values.median())
        except Exception as e:
            print("Filling NaN values with median for feature",e)
            sr_out.fillna(value = sr_values.mode())
            print("Feature","imputed with mode:",sr_values.mode())            
    
    return sr_out

循环

获取空值计数,定义要删除以允许附加的空列列表,并重复 请执行以下操作:对于lst_have_nulls中的每一列,请检查该列的缺失值是否等于,小于或大于5%。 如果更多,请将该列追加到lst_drop。否则,调用手工插补功能。在for循环之后,将所有列放入 lst_drop,就地。

我哪里出错了?如果您需要整个笔记本,我已将其上传kaggle。这是一个链接https://www.kaggle.com/joachimrives/ames-housing-public-problem

更新:测试Anvar的更改答案后问题仍然存在

当我尝试使用Anvar Kurmukov的代码时,我的dataframe列值仍然被交换。我所做的更改是将intfloat添加到要检查的dtype列表中。更改位于for循环内: if dtype in [np.int64,np.float64,int,float]

完整笔记本中的另一部分代码可能有问题。我将需要通过从顶部依次调用df_train.info()单元格来检查其位置。我在公开的笔记本中测试了代码。它在单元格128中。由于某种原因,在运行Anvar的代码后,df_train.info()方法返回了以下内容

    1st Flr SF  2nd Flr SF  3Ssn Porch  Alley   bedroom AbvGr   Bldg Type   Bsmt Cond   Bsmt Exposure   Bsmt Full Bath  Bsmt Half Bath  ... Roof Style  SalePrice   Screen Porch    Street  TotRms AbvGrd   Total Bsmt SF   Utilities   Wood Deck SF    Year Built  Year Remod/Add
1222    1223    534453140   70  RL  50.0    4882    Pave    NaN IR1 Bnk ... 0   0   0   0   0   NaN NaN NaN 0   87000
1642    1643    527256040   20  RL  81.0    13870   Pave    NaN IR1 HLS ... 52  0   0   174 0   NaN NaN NaN 0   455000
1408    1409    905427050   50  RL  66.0    21780   Pave    NaN Reg Lvl ... 36  0   0   144 0   NaN NaN NaN 0   185000
1729    1730    528218050   60  RL  65.0    10237   Pave    NaN Reg Lvl ... 72  0   0   0   0   NaN NaN NaN 0   178900
1069    1070    528180110   120 RL  58.0    10110   Pave    NaN IR1 Lvl ... 48  0   0   0   0   NaN NaN NaN 0   336860

解决方法

tl; dr 而不是try: except,您只需使用if并检查列的dtype即可;您不需要遍历列。

drop_columns = df.columns[df.isna().sum() / df.shape[0] > 0.05]
df.drop(drop_columns,axis=1)

num_columns = []
cat_columns = []

for col,dtype in df.dtypes.iteritems():
    if dtype in [np.int64,np.float64]:
        num_columns.append(col)
    else:
        cat_columns.append(col)
        
df[num_columns] = df[num_columns].fillna(df[num_columns].mean())
df[cat_columns] = df[cat_columns].fillna(df[cat_columns].mode())

make_traintest函数的简短评论:我只需返回2个单独的DataFrame而不是字典,或使用sklearn.model_selection.train_test_split

upd。您可以在列中检查NaN值的数量,但是如果您唯一的目标是估算NaN,则没有必要。

,

答案

我找到了有关为什么我的列被交换的答案。他们实际上并没有被交换。最初的问题是我没有将“ Order”列设置为索引列。要解决PC上笔记本电脑上的问题,我仅向pd.read_csv添加了以下参数和值:index_col = "Order"。这解决了我本地笔记本上的问题。但是,当我在Kaggle笔记本电脑上尝试使用它时,它并没有解决问题

我第一次在笔记本电脑上使用的Ames Housing数据集的版本-由于某种原因-也是交换列的原因。

安瓦尔的密码很好。您可以测试我编写的代码,但是为了安全起见,请遵循Anvar的代码。我的仍在测试中。

测试完成

我修改了在问题中链接的Kaggle笔记本。我使用了实际在PC上使用的数据集。当我这样做时,Anvar Kurmukov的答案给出的代码可以完美地工作。我测试了自己的代码,看起来不错,但是在尝试之前先测试两个版本。我仅使用head()查看了数据集,并手动检查了列输入。如果要检查笔记本,请在以下位置进行: https://www.kaggle.com/joachimrives/ames-housing-public-problem/

为了测试数据集是否存在错误,我创建了数据帧。一个是直接从我上传到Kaggle的本地文件中提取的。另一个使用了我用作输入的Ames Iowa Housing数据集的当前版本。列已正确“对齐”其预期的输入。为了找到期望的列值,我使用了以下来源: http://jse.amstat.org/v19n3/decock/DataDocumentation.txt

以下是我交换数据集时得到的不同结果的屏幕截图:

带有我的本地文件的上传副本:

Data frame df_train has the PID column and all columns match expected input.

使用笔记本版本1中的原始AmesHousing.csv:

The values of PID are assigned to 1st Flr Sf and PID is moved elsewhere.

我使用的导致Kaggle笔记本电脑发生列交换的数据集

https://www.kaggle.com/marcopale/housing enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。