【问题标题】:How to convert continuous data into categorical using bins based on column minimum and maximum value in pandas如何使用基于pandas中列最小值和最大值的bin将连续数据转换为分类数据
【发布时间】:2020-04-30 16:50:29
【问题描述】:

我正在尝试根据所有列的最小值和最大值对数据进行分类。我面临一个手动执行的问题。我想通过传递我的 CSV 文件数据来自动完成。我的数据的形状是(363667,60)。我正在展示我的数据集的样本。

Sno     Col1              col2            col3            col4          col5    
1      84.548913         1.972093         53475.298      63982.83     77064.641304
2      72.036364         5.741337         44580.824      49533.727    71510.181818 
3      15.820000         1.239958         5562.0950      7355.3950    7283.725000
4      26.465409         2.206942         11060.185      12358.4829   16324.478049 
5      239.393443        2.521642         166275.295     214985.754   220683.901639
6      88.474903         1.09879          49609.6409     54794.0424   78830.223938
7      32.766234         1.007994         16966.6147     19215.6753   28802.948052 
8      79.096685         7.605093         39728.3121     47221.88950  71375.127072
9      344.000000        5.440523         225168.904     267927.3714  317527.742857
10     22.459016         1.884006         14640.9180     15854.91803  20288.557377

我对每一列都使用以下代码。

df=pd.read_csv("Oversampling-Balanced.csv", low_memory=False, na_values='?')
bins1=[-0.001,228.0,493.051,812.0,1292.0,10368.5]
# # #name of the groups
gr_names1=['Very_Low','Low','Medium','High','Very_High']
df['lx_pmu_p1fwm_engine_speed_torque_h_x_index_1']=pd.cut(df["lx_pmu_p1fwm_engine_speed_torque_h_x_index_1"],bins1,labels=gr_names1)

我想为所有列而不是手动执行此操作。我想通过传递 CSV 文件的数据框来用更少的代码完成这项任务。

期望的输出是:

Sno     Col1       col2            col3       col4          col5    
1      low         low         low           low          low
2      low         high        very_low      very_low     low
3      very_low    very_low    very_low      very_low     very_low
4      very_low    low         very_low      very_low     very_low 
5      high        low         high          very_high    High
6      low         very_low    low           low          low
7      very_low    very_low    very_low      very_low     very_low 
8      low         very_high   very_low      very_low     low
9      very_high   high        very_high     very_high    very_high
10     very_low    low         very_low      very_low     very_low

【问题讨论】:

  • 你可以使用df.apply
  • @DivyanshuSrivastava 但如何同时对所有列执行此操作。我不知道如何为条件最小值和最大值编写代码
  • @Anki 你能显示你的预期输出吗?
  • 您是如何手动计算 bin 值的?
  • @ChrisSears 我计算一列的最大值并将其除以我想要制作的箱数。

标签: python pandas continuous bins


【解决方案1】:

正如@G Anderson 所提到的,cut 将在您指定 bin 数量时自动计算 bin 范围。实际上,我会推荐 qcut 而不是常规的 cut,因此 bin 范围基于分位数。

以下是为每个数据列添加“bin”列的示例:

import numpy as np
import pandas as pd

data = np.array(
    [[1, 10.0, 1000.0], 
     [2, 20.0, 0.2],
     [3, 30.0, 300.0],
     [4, 40.0, 0.04],
     [5, 50.0, 50.0],
     [6, 60.0, 0.006],
     [7, 70.0, 7.0],
     [8, 80.0, 0.0008],
     [9, 90.0, 9000000],
     ])

df = pd.DataFrame(data=data, columns=["id", "col1", "col2"])

for col in df.columns[1:]:
  df[col+'_bin'] = pd.qcut(df[col], 5, ['Very_Low','Low','Medium','High','Very_High'])

输出:

    id  col1         col2   col1_bin   col2_bin
0  1.0  10.0  1.00000e+03   Very_Low  Very_High
1  2.0  20.0  2.00000e-01   Very_Low        Low
2  3.0  30.0  3.00000e+02        Low       High
3  4.0  40.0  4.00000e-02        Low        Low
4  5.0  50.0  5.00000e+01     Medium       High
5  6.0  60.0  6.00000e-03       High   Very_Low
6  7.0  70.0  7.00000e+00       High     Medium
7  8.0  80.0  8.00000e-04  Very_High   Very_Low
8  9.0  90.0  9.00000e+06  Very_High  Very_High

【讨论】:

  • 我收到错误,因为列中没有唯一值。ValueError: Bin 边缘必须是唯一的:array([ 0. , 6099.6, 7999. , 7999. , 7999. , 28778. ])。您可以通过设置 'duplicates' kwarg 来删除重复的边缘
  • 你能告诉我如何解决这个错误
  • 尝试添加, duplicates='drop'作为qcut()的最后一个参数
  • 你能告诉如何从 col.min(), col.max() 中给出列值的范围来制作 bins
  • @Anki、qcut()cut() 会根据最小值和最大值自动计算 bin 范围,因此您不必编写该代码。使用qcut(),它还会查看数据分布以计算分位数。一般来说,你应该尽可能让 Pandas 为你做事,因为它会更快,更不容易出错。
【解决方案2】:

您可以使用df.apply 在每列上应用自定义categorize 函数,然后您可以使用np.linespace 将列最大值划分为均匀间隔。使用:

import numpy as np

def categorize(col):
    bins = np.linspace(0, col.max(), 6)
    return pd.cut(col, bins, labels=['Very_Low','Low','Medium','High','Very_High'])

df = df.apply(categorize)
print(df)

打印出来:

         Col1       col2       col3       col4       col5
Sno                                                       
1          Low        Low        Low        Low        Low
2          Low       High   Very_Low   Very_Low        Low
3     Very_Low   Very_Low   Very_Low   Very_Low   Very_Low
4     Very_Low        Low   Very_Low   Very_Low   Very_Low
5         High        Low       High  Very_High       High
6          Low   Very_Low        Low        Low        Low
7     Very_Low   Very_Low   Very_Low   Very_Low   Very_Low
8          Low  Very_High   Very_Low   Very_Low        Low
9    Very_High       High  Very_High  Very_High  Very_High
10    Very_Low        Low   Very_Low   Very_Low   Very_Low

【讨论】:

  • 感谢您的回答。但这是针对正在做的一列。但我想做我数据框中的所有列
  • @Anki 根据邮件中的对话,我已经更新了答案。
  • @shubahm Sharma 感谢您的解决方案。代码运行良好。但现在得到 Nan 值。它将所有零值作为 NAN。
猜你喜欢
  • 2023-02-07
  • 2020-04-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-14
  • 2021-02-15
  • 2019-01-02
  • 1970-01-01
相关资源
最近更新 更多