在日常工作中使用Excel可以非常方便地进行数据分析,但是在数据量变大时(超过10000行)时Excel会变得很慢,并且Excel分析出来的数据难以给其它程序(比如用于机器学习的模型训练)使用。
本文以Excel的角度来对照Pandas的相应功能,以帮助快速掌握Pandas进行数据分析。
在Jupyter Notebook中引入Pandas库:
import pandas as pd
from pandas import DataFrame, Series
# 默认UTF-8编码
df = pd.read_csv('./data.txt')
# 打开中文乱码时,可尝试通过指定编码来解决
df = pd.read_csv('./汽车销量.csv', encoding='GB18030')
样例数据:汽车销量.csv
当数据中含有长编码时,Pandas会将该字段作为数值来处理,如果数据中含有空数据的行,Pandas会将该字段作为float64,从而导致长编码后面加上.0
。
解决该问题的方法是导入数据时,指定列的数据类型:
# 将code列设置为字符串(np.object_),将num列设置为浮点数(np.float64)
df = pd.read_csv('./data.txt',
dtype={'code1':pd.np.object_, 'code2':pd.np.object_, 'code3':pd.np.object_, 'num1':pd.np.float64, 'num2':pd.np.float64 })
导入数据后,执行df.info()
检查列的格式是否正确。
在导入数据时也可以通过usecols
参数指定只导入特定的列:
df = pd.read_csv('./data.txt', usecols = ['code1', 'code3'])
重命名列:
df = df.rename(columns={'code1': '代码1', 'num1': '数值1'}, errors='raise')
设置索引列:
df = df.set_index('车型', drop=False)
如果不指定索引列,默认索引列为一个从0开始递增的自然数数列。
# 默认使用UTF-8编码
df.to_csv('./out.csv', index=None)
# 指定GB18030编码
df.to_csv('./out.csv', index=None, encoding='GB18030')
# 遇到小数导出后精度问题,可以通过指定保留的小数位数来解决,比如保留5位小数
df.to_csv('./out.csv', index=None, float_format='%.5f')
Excel中的”表格“对应Pandas库的DataFrame:
查看表格头10条记录:
df.head(10)
查看表格尾10条记录:
df.tail(10)
查看表格10条抽样记录:
df.sample(10)
查看表格缩略数据:
df
查看表格统计数据:
df.describe()
查看表格的行数和列数:
df.shape
# 行数
df.shape[0]
# 列数
df.shape[1]
Excel中的”行“对应Pandas的DataFrame的一个切片(Slice):
df[row_index_slice | bool_array]
# 或根据索引列的行标签选取
df.loc[row_label | row_label_array | row_label_slice]
# 或根据索引列的行号选取,行号从0开始
df.iloc[row_index | row_index_array | row_index_slice]
注意:Pandas的行号从0开始。
根据行标签选取行:
“车型”为“丰田卡罗拉”的行:
df[df['车型'] == '丰田卡罗拉']
# 或
df.loc['丰田卡罗拉']
"车型“为”大众朗逸“和”大众速腾“的行:
df[df['车型'].isin(['大众朗逸','大众速腾'])]
# 或
df.loc[['大众朗逸','大众速腾']]
根据行号选取行:
第1行:
df[:1]
# 或
df.iloc[0]
前3行:
df[:3]
# 或
df.iloc[:3]
第5行到第10行:
df[4:10]
# 或
df.iloc[4:10]
第8行:
df[7:8]
# 或
df.iloc[7]
后3行:
df[-3:]
# 或
df.iloc[-3:]
Excel中的”列“对应Pandas的Series:
df[column_label | column_label_array]
# 或根据列名选取列
df.loc[: , column_label | column_label_array | column_label_slice]
# 或根据列号选取列
df.iloc[: , column_index | column_index_array | column_index_slice]
根据列名选取列:
”车型“一列:
df['车型']
# 或
df.车型
# 或
df.loc[:, '车型']
”车型“和”销量“两列:
df[['车型','销量']]
# 或
df.loc[: , ['车型','销量']]
从”车型“到”销量“的所有列:
df.loc[: , '车型':'销量']
根据列号选取列
第1列:
df.iloc[:, :1]
从第2到第3列:
df.iloc[:, 1:3]
最后1列:
df.iloc[:, -1:]
Excel中的”单元格“对应Pandas的DataFrame的一个切片(Slice):
# 根据行标签和列名选取一个或多个单元格
df.loc[row_label | row_label_array | row_label_slice, column_label | column_label_array | column_label_slice ]
# 根据行号和列号选取一个或多个单元格
df.iloc[row_index | row_index_array | row_index_slice, column_index | column_index_array | column_index_slice ]
根据行标签和列名选取一个或多个单元格:
"吉利博瑞"的”销量“:
df.loc['吉利博瑞','销量']
"吉利博瑞"的"厂商"和”销量“:
df.loc['吉利博瑞',['厂商','销量']]
"大众迈腾"和"大众捷达"的"厂商"和”销量“:
df.loc[['大众迈腾','大众捷达'],['厂商','销量']]
"吉利博瑞"的从"厂商"到”销量“列:
df.loc['吉利博瑞','厂商':'销量']
根据行号和列号选取一个或多个单元格:
第1行第2列:
df.iloc[0,1]
第5行到第10行的第2列到第3列:
df.iloc[4:10, 1:3]
复制“DS 5”行,插入到最后:
df2 = df.append(df.loc['DS 5'])
复制”销量“列,插入到最后,新列名为”备注“:
df['备注'] = df['销量']
在最前面新增一列”排名“,从1开始自动填充该列:
df.insert(0, "排名", range(1, len(df) + 1))
删除”DS 5"行:
df.drop('DS 5', axis=0)
删除”备注“列:
df.drop(columns='备注')
# 或
df.drop('备注', axis=1)
厂商为“东风日产”的记录:
df[df['厂商'] == '东风日产']
厂商为“东风日产”的总销量:
df[df['厂商'] == '东风日产']['销量'].sum()
厂商为“东风日产”的平均销量:
df[df['厂商'] == '东风日产']['销量'].mean()
厂商为“东风日产”的计数:
df[df['厂商'] == '东风日产']['销量'].count()
厂商为“东风日产”的最大销量:
df[df['厂商'] == '东风日产']['销量'].max()
厂商为“东风日产”的最小销量:
df[df['厂商'] == '东风日产']['销量'].min()
多选:厂商为“一汽大众”和“一汽丰田”的记录:
df[df['厂商'].isin(['一汽大众', '一汽丰田'])]
反选:厂商不为“上汽通用”的记录:
df[df['厂商'] != '东风日产']
反选:厂商不为“一汽大众”和“一汽丰田”的记录:
# Python使用波浪号~表示“非”操作
df[~df['厂商'].isin(['一汽大众', '一汽丰田'])]
# 或
df[df['厂商'].isin(['一汽大众', '一汽丰田']) == False]
升序排序:
df.sort_values('销量', ascending=True, inplace=True)
降序排序:
df.sort_values('销量', ascending=False, inplace=True)
”厂商“列的唯一值:
# unique array
df['厂商'].unique()
# size of unique array
len(df['厂商'].unique())
先故意插入两个重复行:
df2 = df.append(df.iloc[-2:])
重复记录数:
df2.duplicated().sum()
显示重复记录:
df2[df2.duplicated()]
删除重复记录:
df2.drop_duplicates(inplace=True)
空字符串:
先故意将“DS 5"和"一汽骏派A70E"的厂商设为空字符串''
:
df2.loc['DS 5', '厂商'] = ''
df2.loc['一汽骏派A70E', '厂商'] = ''
空字符串记录数:
(df2['厂商'].astype(bool) == False).sum()
查找空字符串记录:
df2[df2['厂商'].astype(bool) == False]
空值:
替换空字符串为NaN:
df2['厂商'].replace('', pd.np.nan, inplace=True)
替换后NaN记录数:
df2['厂商'].isna().sum()
查找NaN记录数:
df2[df2['厂商'].isna()]
删除NaN记录:
df2.dropna(subset=['厂商'], inplace=True)
替换NaN记录:
df2['厂商'].fillna(value='Unknown', inplace=True)
查看各列的数据类型:
df.dtypes
转换成数值:
s = pd.Series(['apple', '1.0', '2', -3])
# 忽略不是数值的值
s2 = pd.to_numeric(s, errors='ignore')
# 将不是数值的值替换成NaN
s2 = pd.to_numeric(s, errors='coerce')
# 转换时作类型转换(降低精度)
s2 = pd.to_numeric(s, errors='coerce', downcast='float')
转换成日期:
s = pd.Series(['3/11/2000', '3/12/2000', '3/13/2000'])
# 将不是日期的值替换成NaT
s2 = pd.to_datetime(s, errors='coerce')
转换成字符串:
s3 = s2.astype(str)
新增”销量过万车型“列,对销量过万的车型该列值为Y:
def sales_flag(value):
if value >= 10000:
return 'Y'
else:
return 'N'
df2['销量过万车型'] = df2['销量'].apply(sales_flag)
查看销量过万车型:
df2[df2['销量过万车型'] == 'Y']
按”厂商“统计销量:
df.groupby('厂商')['销量'].sum()
# 或
df.pivot_table(index='厂商', values='销量', aggfunc='sum')
按”厂商“统计记录数:
df['厂商'].value_counts()
# 或
df.groupby('厂商')['销量'].count()
按”厂商“统计平均销量:
df.groupby('厂商')['销量'].mean()
按”厂商“统计最高销量:
df.groupby('厂商')['销量'].max()
按”厂商“统计最低销量:
df.groupby('厂商')['销量'].min()
TODO: 更多的分类统计场景