首页Python【Python数据分析】3...

【Python数据分析】33.数据清洗与准备——数据转换2


本系列文章配套代码获取有以下三种途径:

  • 可以在以下网站查看,该网站是使用JupyterLite搭建的web端Jupyter环境,因此无需在本地安装运行环境即可使用,首次运行浏览器需要下载一些配置文件(大约20M):

https://returu.github.io/Python_Data_Analysis/lab/index.html
链接:https://pan.baidu.com/s/1MYkeYeVAIRqbxezQECHwcA?pwd=mnsj 提取码:mnsj
  • 前往GitHub详情页面,单击 code 按钮,选择Download ZIP选项:
https://github.com/returu/Python_Data_Analysis

根据《Python for Data Analysis 3rd Edition》翻译整理

—————————————————–

1.离散化和分箱:

在日常的数据分析处理工作中,连续性数据经常需要做离散化或者分箱处理。
例如,需要把一组年龄数据分成离散的年龄段组中。
1# 将年龄按照18~25,26~35,36~60,60~100分组
2>>> ages = [22,21,25,28,21,23,36,33,65,46,40,39]
3>>> bins = [18,25,35,60,100]
  • cut()方法

pandas.cut方法返回的是一个特殊的Categorical对象。

1>>> ages_cate = pd.cut(ages,bins)
2>>> ages_cate
3[(1825], (1825], (1825], (2535], (1825], ..., (2535], (60100], (3560], (3560], (3560]]
4Length: 12
5Categories (4, interval[int64, right]): [(1825] < (2535] < (3560] < (60100]]

输出结果描述了 pandas.cut 计算的 bin。每个 bin 由一个特殊的(pandas 独有的)区间值类型标识,其中包含每个 bin 的下限和上限。

1# 类别数组
2>>> ages_cate.categories
3IntervalIndex([(1825], (2535], (3560], (60100]], dtype='interval[int64, right]')
4
5# 不同年龄在类别数组中的索引值
6>>> ages_cate.codes
7array([000100213222], dtype=int8)


 1# 类别数组
2>>> ages_cate.categories
3IntervalIndex([(1825], (2535], (3560], (60100]], dtype='interval[int64, right]')
4
5# 不同年龄在类别数组中的标签
6>>> ages_cate.codes
7array([000100213222], dtype=int8)
8
9# pandas.cut 结果中的 箱(bin)数量的 计数
10>>> pd.value_counts(ages_cate)
11(1825]     5
12(3560]     4
13(2535]     2
14(60100]    1
15dtype: int64

默认情况下,区间的左边为开放的(不包括)、右边为封闭的(包括),可以通过传递 right=False 参数改变区间形式。

1>>> ages_cate = pd.cut(ages,bins)
2>>> ages_cate.categories
3IntervalIndex([(1825], (2535], (3560], (60100]], dtype='interval[int64, right]')
4
5>>> ages_cate2 = pd.cut(ages,bins,right=False)
6>>> ages_cate2.categories
7IntervalIndex([[1825), [2535), [3560), [60100)], dtype='interval[int64, left]')

还可以通过向 labels 参数传递一个列表或数组来自定义箱名。

1>>> ages = [22,21,25,28,21,23,36,33,65,46,40,39]
2>>> bins = [18,25,35,60,100]
3>>> group_names =['未成年','成年','中年','老年']
4
5>>> ages_cate = pd.cut(ages,bins,labels=group_names)
6>>> ages_cate
7['未成年''未成年''未成年''成年''未成年', ..., '成年''老年''中年''中年''中年']
8Length: 12
9Categories (4, object): ['未成年' < '成年' < '中年' < '老年']

也可以传入希望切分的箱的数量,系统会根据最大值和最小值自动计算出等长的箱,其中precision选项用于设置精度限制。

1>>> ages = [22,21,25,28,21,23,36,33,65,46,40,39]
2>>> ages_cate = pd.cut(ages,4,precision=2)
3>>> ages_cate
4[(20.9632.0], (20.9632.0], (20.9632.0], (20.9632.0], (20.9632.0], ..., (32.043.0], (54.065.0], (43.054.0], (32.043.0], (32.043.0]]
5Length: 12
6Categories (4, interval[float64, right]): [(20.9632.0] < (32.043.0] < (43.054.0] < (54.065.0]]
  • qcut()方法

pandas.qcut 方法是一个与分箱操作密切相关的函数,是基于样本分位数进行分箱操作。取决于数据分布,pandas.cut 通常不会使得每个箱中具有相同数量的样本点。由于pandas.qcut 使用样本分位数,可以获得等长的箱。
 1>>> data = np.random.randn(100)
2>>> data_cate = pd.qcut(data,4# 切分成四份
3>>> data_cate
4[(-2.092, -0.698], (-2.092, -0.698], (-0.2420.341], (-0.698, -0.242], (-0.2420.341], ..., (-2.092, -0.698], (-0.698, -0.242], (0.3412.385], (-0.698, -0.242], (-0.2420.341]]
5Length: 100
6Categories (4, interval[float64, right]): [(-2.092, -0.698] < (-0.698, -0.242] < (-0.2420.341] < (0.3412.385]]
7
8>>> pd.value_counts(data_cate)
9(-2.092, -0.698]    25
10(-0.698, -0.242]    25
11(-0.2420.341]     25
12(0.3412.385]      25
13dtype: int64
当然也可以传入自定义的分位数(0到1之间的数据,包括边)。
 1>>> data_cate = pd.qcut(data,[0,0.1,0.5,0.9,1])
2>>> data_cate
3[(-2.092, -1.17], (-2.092, -1.17], (-0.2421.038], (-1.17, -0.242], (-0.2421.038], ..., (-2.092, -1.17], (-1.17, -0.242], (1.0382.385], (-1.17, -0.242], (-0.2421.038]]
4Length: 100
5Categories (4, interval[float64, right]): [(-2.092, -1.17] < (-1.17, -0.242] < (-0.2421.038] < (1.0382.385]]
6
7>>> pd.value_counts(data_cate)
8(-1.17, -0.242]    40
9(-0.2421.038]    40
10(-2.092, -1.17]    10
11(1.0382.385]     10
12dtype: int64

2.检测和过滤异常值

过滤或转换异常值主要是应用数组操作的问题。

例如,需要将DataFrame中的数值限制在 -50 到50 之间,大于50的设置为50,小于-50的设置为-50。

1>>> data = pd.DataFrame(np.random.randint(-100,100,(64)))
2>>> data

假设你想在其中一列中查找绝对值超过 50 的值。

1>>> col = data[2]
2>>> col[col.abs() > 50]
33   -84
44   -53
55   -81
6Name: 2dtype: int32

如要选择值超过 50 或 –50 的所有行,可以在布尔值DataFrame上使用 any 方法。

1>>> data[(data.abs() > 50).any(axis="columns")]

通过np.sign(),限制值超出 –50 到 50的区间。

其中, np.sign() 方法之前介绍过,是根据数据中值的正负分别生成1和-1的数值。

1>>> data[(data.abs() > 50)] = np.sign(data)*50
2>>> data


本篇文章来源于微信公众号: 码农设计师

RELATED ARTICLES

欢迎留下您的宝贵建议

Please enter your comment!
Please enter your name here

- Advertisment -

Most Popular

Recent Comments