"数据整理"是一个被广泛使用的词,经常用于描述将原始数据转换成整洁的、组织合理的形式以供使用的过程,对于机器学习来说,它仅仅是数据“预处理”中的一个步骤。在整理数据的时候,最常见的数据结构是“数据帧(data frame)”,下面的内容我们将借助另一个常用的库pandas库来帮助我们完成一系列操作。
在pandas中有很多方法可以创建一个新的数据帧对象,一个简单的方法是DataFrame创建一个空数据帧并分别定义好每一列:
import pandas as pd
# 创建数据帧
dataframe = pd.DataFrame()
# 增加列
dataframe['name'] = ['John', 'Tom']
dataframe['age'] = [38, 29]
dataframe['Driver'] = [True, False]
# 创建一行
new_person = pd.Series(['Roy', 30, True], index=['name', 'age', 'Driver'])
dataframe = dataframe.append(new_person, ignore_index=True)
print(dataframe)
name age Driver
0 John 38 True
1 Tom 29 False
2 Roy 30 True
# 接着上面的代码
# 查看维数
print(dataframe.shape)
#查看描述性统计量
print(dataframe.describe())
(3, 3)
age
count 3.000000
mean 32.333333
std 4.932883
min 29.000000
25% 29.500000
50% 30.000000
75% 34.000000
max 38.000000
利用经典数据集:泰坦尼克号,来练习浏览这种大数据集。
import pandas as pd
# 载入准备好的泰坦尼克号数据集
dataframe = pd.read_csv('train.csv')
# 打印第一行
print(dataframe.iloc[0])
# 打印第2、3、4行
print(dataframe.iloc[1:4])
# 打印前2行
print(dataframe.iloc[:2])
PassengerId 1
Survived 0
Pclass 3
Name Braund, Mr. Owen Harris
Sex male
Age 22
Name: 0, dtype: object
PassengerId Survived Pclass Name Sex Age
1 2 1 1 Cumings, Mrs. John Bradley female 38.0
2 3 1 3 Heikkinen, Miss. Laina female 26.0
3 4 1 1 Futrelle, Mrs. Jacques Heath female 35.0
PassengerId Survived Pclass Name Sex Age
0 1 0 3 Braund, Mr. Owen Harris male 22.0
1 2 1 1 Cumings, Mrs. John Bradley female 38.0
【小贴士】:若存在数据集打印不完整,中间出现...的问题,可以利用如下代码设置:
# 核心代码,设置显示的最大列、宽等参数,消掉打印不完全中间的省略号
pd.set_option('display.max_columns', 1000)
pd.set_option('display.width', 1000)
pd.set_option('display.max_colwidth', 1000)
数据帧的索引不必非得是数值型,只要是某一列在数据帧中每一行的值是唯一的,就可以将其设置为索引。举个例子,我们可以将乘客的名字设置为索引,然后通过名字在选择行:
# 将“Name”设置为索引
dataframe = dataframe.set_index(dataframe['Name'])
# 查看Name为Heikkinen, Miss. Laina的行
print(dataframe.loc['Heikkinen, Miss. Laina'])
PassengerId 3
Survived 1
Pclass 3
Name Heikkinen, Miss. Laina
Sex female
Age 26
Name: Heikkinen, Miss. Laina, dtype: object
为了能选择一行或部分行,pandas提供了两个方法:
(1)loc:当数据帧的索引为一个标签(例如:一个字符串)时,比较常用。
(2)iloc:根据“行号”来查找,不管索引时数值型还是标签。
本质:利用布尔索引来筛选。
# 筛选出Sex值为female的前3名
print(dataframe[dataframe['Sex'] == 'female'].head(3))
# 筛选出Age值大于或等于55岁,且为女性的前3名
print(dataframe[(dataframe['Sex'] == 'female') & (dataframe['Age'] >= 55)].head(3))
PassengerId Survived Pclass Name Sex Age
1 2 1 1 Cumings, Mrs. John Bradley female 38.0
2 3 1 3 Heikkinen, Miss. Laina female 26.0
3 4 1 1 Futrelle, Mrs. Jacques Heath female 35.0
PassengerId Survived Pclass Name Sex Age
11 12 1 1 Bonnell, Miss. Elizabeth female 58.0
15 16 1 2 Hewlett, Mrs. female 55.0
195 196 1 1 Lurette, Miss. Elise female 58.0
# replace():前面[]是原列表中的值,后面[]是即将替换的值
print(dataframe.replace(['female', 'male'], ['women', 'men']).head(4))
PassengerId Survived Pclass Name Sex Age
0 1 0 3 Braund, Mr. Owen Harris men 22.0
1 2 1 1 Cumings, Mrs. John Bradley women 38.0
2 3 1 3 Heikkinen, Miss. Laina women 26.0
3 4 1 1 Futrelle, Mrs. Jacques Heath women 35.0
【小提示】:replace()可以接受正则表达式。
rename(): 重命名列,接受字典参数,可以同时改变多个列名。
# 重命名列,并打印前两行
print(dataframe.rename(columns={'Pclass': 'Passenger Class'}).head(2))
print(dataframe.rename(columns={'Pclass': 'Passenger Class', 'Sex': 'Gender'}).head(2))
print('Max:', dataframe['Age'].max())
print('Min:', dataframe['Age'].min())
print('Mean:', dataframe['Age'].mean())
print('Sum:', dataframe['Age'].sum())
print('Count:', dataframe['Age'].count())
print('Mode:', dataframe['Age'].mode()) //众数
print('Median:', dataframe['Age'].median()) //中位数
print('Var:', dataframe['Age'].var()) //方差
print('Std:', dataframe['Age'].std()) //标准差
Max: 80.0
Min: 0.42
Mean: 29.69911764705882
Sum: 21205.17
Count: 714
Mode: 0 24.0
dtype: float64
Median: 28.0
Var: 211.01912474630802
Std: 14.526497332334042
unique()与nunique()方法
# 查看Sex中的唯一值
print(dataframe['Sex'].unique())
# 统计Sex和Pclass中每个唯一值的个数
print(dataframe['Sex'].value_counts())
print(dataframe['Pclass'].value_counts())
# 统计Pclass中唯一值的个数
print(dataframe['Pclass'].nunique())
['male' 'female']
male 577
female 314
Name: Sex, dtype: int64
3 491
1 216
2 184
Name: Pclass, dtype: int64
3
实际应用当中,大部分数据中都存在缺失值,如果不对缺失值处理,直接进行数据分析,有可能会造成不可估量的影响,所以处理缺失值很重要。最常见的解决方案:isnull和notnull都能返回布尔类型的值,来表示一个值是否有缺失:
# 筛选出缺失值,查看前3行
print(dataframe[dataframe['Age'].isnull()].head(3))
PassengerId Survived Pclass Name Sex Age
5 6 0 3 Moran, Mr. James male NaN
17 18 1 2 Williams, Mr. Charles Eugene male NaN
19 20 1 3 Masselmani, Mrs. Fatima female NaN
在数据整理中,缺失值是很常见的问题,很多人都低估了处理缺失值的难度。Pandas使用Numpy的NaN("Not A Number",意为“不是一个数字”)来表示缺失值,但是Pandas本身并没有实现NaN,如果直接使用,便会得到一条错误信息:
dataframe['Sex'] = dataframe['Sex'].replace('male', NaN)
Traceback (most recent call last):
dataframe['Sex'] = dataframe['Sex'].replace('male', NaN)
NameError: name 'NaN' is not defined
因此,要想使用NaN,就需要导入NumPy库:
# 导入numpy库,再使用NaN
import numpy as np
print(dataframe.replace('male', np.NaN).head(1))
数据集中还会使用其他特殊值来表示缺失值:NONE、-999或者 . 。
drop():删除列
# 参数axis=1为列
# 删除标签为'Age'的列
print(dataframe.drop('Age', axis=1).head(2))
# 删除标签为'Age'和'Sex'的列
print(dataframe.drop(['Age', 'Sex'], axis=1).head(2))
# 利用columns:通过列的下标来指定列
print(dataframe.drop(dataframe.columns[1], axis=1).head(2))
PassengerId Survived Pclass Name Sex
0 1 0 3 Braund, Mr. Owen Harris male
1 2 1 1 Cumings, Mrs. John Bradley female
PassengerId Survived Pclass Name
0 1 0 3 Braund, Mr. Owen Harris
1 2 1 1 Cumings, Mrs. John Bradley
PassengerId Pclass Name Sex Age
0 1 3 Braund, Mr. Owen Harris male 22.0
1 2 1 Cumings, Mrs. John Bradley female 38.0
还有一种删除方法是del dataframe['Age'], 它是在pandas内部调用方式,不建议使用。
【小提示】:不要使用inplace=True参数,会将数据帧视为可变对象;而在不设置参数时,则默认是为不可变对象,这会为我们省去很多麻烦。
可以利用drop()方法,但是更实用的是利用布尔条件。
# 删除:标签Sex为‘male’的行
dataframe = dataframe[dataframe['Sex'] != 'male']
# 删除:标签Name为‘Mr. Owen Harris’的行
dataframe = dataframe[dataframe['Name'] != 'Mr. Owen Harris']
# 删除:行下标为0的行
dataframe = dataframe[dataframe.index != 0]
drop_duplicates()方法:处理重复行
# 无任何参数的时候,drop_duplicates()只会删除完全一样的行
dataframe = dataframe.drop_duplicates()
# subset参数:选择根据哪个标签判断是否为重复行
dataframe = dataframe.drop_duplicates(subset=['Sex'])
print(dataframe)
# 此使,仅剩下2行数据
PassengerId Survived Pclass Name Sex Age
0 1 0 3 Braund, Mr. Owen Harris male 22.0
1 2 1 1 Cumings, Mrs. John Bradley female 38.0
评论