数据清洗与准备:使用函数或映射进行数据交换,替代值,重命名轴索引, 离散化和分箱,检测和过滤异常值

7.2.2 使用函数或映射进行数据交换

data = pd.DataFrame({'food': ['bacon', 'pulled pork', 'bacon',
                              'Pastrami', 'corned beef', 'Bacon',
                              'pastrami', 'honey ham', 'nova lox'],
                     'ounces': [4, 3, 12, 6, 7.5, 8, 3, 5, 6]})
data           # 关于肉类的数据,培根,手撕猪肉,熏牛肉,咸牛肉,蜂蜜火腿,盐渍三文鱼。。。。。。

meat_to_animal = {            # 来添加一列表明每种肉的来源,,
  'bacon': 'pig',
  'pulled pork': 'pig',
  'pastrami': 'cow',
  'corned beef': 'cow',
  'honey ham': 'pig',
  'nova lox': 'salmon'
}

lowercased=data['food'].str.lower()       # 可以看到一些肉类时大写的,使用 str.lower()方法将所有值都小写。
lowercased
0          bacon
1    pulled pork
2          bacon
3       pastrami
4    corned beef
5          bacon
6       pastrami
7      honey ham
8       nova lox
Name: food, dtype: object


data['animal']=lowercased.map(meat_to_animal)     # series 的map 方法接收一个函数或一个包含映射关系的字典型对象。
data
    food	ounces	animal
0	bacon	4.0	pig
1	pulled pork	3.0	pig
2	bacon	12.0	pig
3	Pastrami	6.0	cow
4	corned beef	7.5	cow
5	Bacon	8.0	pig
6	pastrami	3.0	cow
7	honey ham	5.0	pig
8	nova lox	6.0	salmon

data['animal'].map(lambda x:meat_to_animal[x.lower()])    # 也可以传入一个可以完成所有工作的函数,,感觉不是很好理解啊。

使用 map 是一种可以便捷执行按元素转换及其他清洗相关操作的方法。

7.2.3 替代值

使用 fillna 填充缺失值时通用值替换的特殊案例。map 可以用来修改一个对象中的子集的值,但是 replace 提供了更为简单灵活的实现。

data=pd.Series([1,-999,2,-999,-1000,3])
data.replace([-1000,-999],np.nan)      # 可以传入 inplace = True, 来改变原对象。
0       1.0
1       NaN
2       2.0
3       NaN
4       NaN
5       3.0
dtype: float64

data.replace([-999,-1000],[np.nan,0])      # 不同的值替换为不同的值

data.replace({-999:np.nan,-1000:0})        # 也可以通过字典传递

data.replace 与 data.str.replace 是不同的,前一个是对字符串进行按元素替代的。

7.2.4 重命名轴索引

和Series 中的值一样,可以通过函数或某种形式的映射对轴标签进行类似的转换,生成新的且带有不同标签的对象,你可以可以在不生成新的数据结构的情况下修改轴。

data = pd.DataFrame(np.arange(12).reshape((3, 4)),
                    index=['Ohio', 'Colorado', 'New York'],
                    columns=['one', 'two', 'three', 'four'])
transform=lambda x:x[:4].upper()       # 与 series 类似,轴索引也有一个 map 方法。这里只要前四个字母
data.index.map(transform)
Index(['OHIO', 'COLO', 'NEW '], dtype='object')

data.index=data.index.map(transform)       # 应用到原 dataframe 上



data.rename(index=str.title,columns=str.upper)       # 这个方法不会修改原数据集
	ONE	TWO	THREE	FOUR
Ohio	0	1	2	3
Colorado	4	5	6	7
New York	8	9	10	11

data.rename(index={'Ohio':'eee'},columns={'three':'三'},inplace=True)   # rename 可以结合字典型对象使用,修改原值
	one	two	三	four
eee	0	1	2	3
Colorado	4	5	6	7
New York	8	9	10	11

7.2.5 离散化和分箱

连续值经常需要离散化,或者分离成’箱子‘ 进行分析,假如你在研究一群人的数据,想对他们进行分组,放入离散的年龄框中。

并且将这些年龄分为 18~25, 26~35 等若干组,可以使用pandas的 cut 方法:

ages = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]

bins=[18,25,35,60,100]     # 各组的下界
cats=pd.cut(ages,bins)
cats
[(18, 25], (18, 25], (18, 25], (25, 35], (18, 25], ..., (25, 35], (60, 100], (35, 60], (35, 60], (25, 35]]
Length: 12
Categories (4, interval[int64]): [(18, 25] < (25, 35] < (35, 60] < (60, 100]]

pandas 返回的对象是一个特殊的 Categorical 对象。输出的是由pandas.cut 计算出的箱。你可以将它当作一个表示箱名的字符串数组;他在内部包含一个categories 数组,它指定了不同的类别名称以及codes 属性中的ages 数据标签:

cats.codes
array([0, 0, 0, 1, 0, 0, 2, 1, 3, 2, 2, 1], dtype=int8)

cats.categories
IntervalIndex([(18, 25], (25, 35], (35, 60], (60, 100]],
              closed='right',
              dtype='interval[int64]')
              
pd.value_counts(cats)                 # 这个是对 pandas.cut 结果中的箱数量的计数。。
(18, 25]     5
(35, 60]     3
(25, 35]     3
(60, 100]    1
dtype: int64

pd.cut(ages,[18,26,36,61,100],right=False)      # 默认是左开右闭,right=False 改一下
[[18, 26), [18, 26), [18, 26), [26, 36), [18, 26), ..., [26, 36), [61, 100), [36, 61), [36, 61), [26, 36)]
Length: 12
Categories (4, interval[int64]): [[18, 26) < [26, 36) < [36, 61) < [61, 100)]


group_names = ['小年轻', '步入中年', '中年', '大叔']
pd.cut(ages, bins, labels=group_names)              # 通过 laberls 传递一个列表或数组来传入自定义的箱名。
[小年轻, 小年轻, 小年轻, 步入中年, 小年轻, ..., 步入中年, 大叔, 中年, 中年, 步入中年]
Length: 12
Categories (4, object): [小年轻 < 步入中年 < 中年 < 大叔]


data=np.random.rand(20)
pd.cut(data,4,precision=2)     # 传递个整数作为箱的个数,根据最大值最小值计算出等长的箱,precision=2是限制精度为两位。
[(0.75, 0.99], (0.25, 0.5], (0.5, 0.75], (0.5, 0.75], (0.0017, 0.25], ..., (0.75, 0.99], (0.75, 0.99], (0.75, 0.99], (0.5, 0.75], (0.5, 0.75]]
Length: 20
Categories (4, interval[float64]): [(0.0017, 0.25] < (0.25, 0.5] < (0.5, 0.75] < (0.75, 0.99]]

qcut 是一个与分箱密切相关的函数,基于样本分数位进行分箱。使用 cut 通常不会使每个箱具有相同数据量的数据点。但是 qcut 可以获得等长的箱:

分位数(Quantile),亦称分位点,是指将一个随机变量的概率分布范围分为几个等份的数值点,常用的有中位数(即二分位数)、四分位数、百分位数等。

data=np.random.randn(1000)         # 正态分布
cats=pd.qcut(data,4)
pd.value_counts(cats)
(0.689, 3.234]      250
(0.013, 0.689]      250
(-0.688, 0.013]     250
(-2.714, -0.688]    250
dtype: int64

cats=pd.qcut(data,[0,0.1,0.5,0.9,1])      # 自定义分位数(0到9之间,包括边),这里就是  1:4:4:1
pd.value_counts(cats)
(0.00551, 1.277]     400
(-1.312, 0.00551]    400        # 这里按大小排一下就是 1 4 4 1
(1.277, 3.178]       100
(-3.726, -1.312]     100
dtype: int64

7.2.6 检测和过滤异常值

data=pd.DataFrame(np.random.randn(1000,4))
data.describe()
               0	1	2	3
count	1000.000000	1000.000000	1000.000000	1000.000000
mean	-0.046855	-0.037590	-0.025516	0.000239
std	0.996804	0.968972	0.974601	0.985552
min	-2.825149	-3.102762	-3.101988	-3.450912
25%	-0.716746	-0.679858	-0.708844	-0.696253
50%	-0.073610	-0.040148	-0.057884	0.029316
75%	0.636879	0.621425	0.655887	0.702969
max	3.021937	2.704446	3.175656	2.715394

col = data[2]
col[np.abs(col)>3]          # 选出第三行中绝对值大于三的值
123    3.175656
612    3.142433
749   -3.101988
Name: 2, dtype: float64

data[(np.abs(data)>3).any(1)]           # 选出绝对值大于三的所有行,这行里有一个就行,使用 any() 方法。
	0	1	2	3
80	-1.662567	-0.507703	-0.670220	-3.450912
117	-2.185866	0.026732	0.827076	-3.239595
123	-0.930652	1.675178	3.175656	0.043078
155	1.010232	-3.102762	0.343464	-1.268382
278	3.021937	0.703424	2.160534	0.119472
612	-1.131423	-1.296522	3.142433	-0.019182
749	-0.439125	0.085791	-3.101988	0.238118
821	-0.504162	-1.001123	1.387467	-3.163276


np.sign(data).head()           # 这个方法根据数据的正负生成 1 或 -1
    0	1	2	3
0	-1.0	1.0	1.0	-1.0
1	-1.0	-1.0	-1.0	1.0
2	-1.0	1.0	-1.0	1.0
3	-1.0	-1.0	-1.0	1.0
4	1.0	-1.0	1.0	-1.0
 
data[np.abs(data)>3]=np.sign(data) *3                # 这样可以将绝对值大于三的值都改成3/-3,来限制数值

猜你喜欢

转载自blog.csdn.net/weixin_46192930/article/details/106637894
今日推荐