Pandas——掌握DataFrame的常用操作
- 一、查看DataFrame的常用属性
- 二、查改增删DataFrame数据
- 2.1、查看访问DataFrame中的数据
- 2.1.1、使用字典访问内部数据的方式访问DataFrame单列数据
- 2.1.2、使用访问属性的方式访问DataFrame单列数据
- 2.1.3、DataFrame单列多行数据获取
- 2.1.4、访问DataFrame多列的多行数据
- 2.1.5、访问DataFrame多行数据
- 2.1.6、使用DataFrame的head和tail方法获取多行数据
- 2.1.7、使用loc和iloc 实现单列切片
- 2.1.8、使用 loc、iloc 实现多列切片
- 2.1.9、使用loc、iloc 实现花式切片
- 2.1.10、使用loc和iloc 实现条件切片
- 2.1.11、使用iloc 实现条件切片
- 2.1.12、使用loc、iloc、ix实现切片比较
- 2.2、更改DataFrame 中的数据
- 2.3、为DataFrame增添数据
- 2.4、删除某列或某行数据
- 三、描述分析DataFrame数据
- 四、案例操作
一、查看DataFrame的常用属性
1.1、订单详情表的4个基本属性
from sqlalchemy import create_engine
import pandas as pd
# 创建数据库连接
engine = create_engine('mysql+pymysql://root:1234@127.0.0.1:\
3306/testdb?charset=utf8')
detail = pd.read_sql_table('meal_order_detail1', con=engine)
print('订单详情表的索引为:', detail.index)
print('订单详情表的所有值为:', '\n', detail.values)
print('订单详情表的列名为:', '\n', detail.columns)
print('订单详情表的数据类型为:', '\n', detail.dtypes)
订单详情表的索引为: RangeIndex(start=0, stop=2779, step=1)
订单详情表的所有值为:
[['2956' '417' '610062' ... 'NA' 'caipu/104001.jpg' '1442']
['2958' '417' '609957' ... 'NA' 'caipu/202003.jpg' '1442']
['2961' '417' '609950' ... 'NA' 'caipu/303001.jpg' '1442']
...
['6756' '774' '609949' ... 'NA' 'caipu/404005.jpg' '1138']
['6763' '774' '610014' ... 'NA' 'caipu/302003.jpg' '1138']
['6764' '774' '610017' ... 'NA' 'caipu/302006.jpg' '1138']]
订单详情表的列名为:
Index(['detail_id', 'order_id', 'dishes_id', 'logicprn_name',
'parent_class_name', 'dishes_name', 'itemis_add', 'counts', 'amounts',
'cost', 'place_order_time', 'discount_amt', 'discount_reason',
'kick_back', 'add_inprice', 'add_info', 'bar_code', 'picture_file',
'emp_id'],
dtype='object')
订单详情表的数据类型为:
detail_id object
order_id object
dishes_id object
logicprn_name object
parent_class_name object
dishes_name object
itemis_add object
counts float64
amounts float64
cost object
place_order_time datetime64[ns]
discount_amt object
discount_reason object
kick_back object
add_inprice object
add_info object
bar_code object
picture_file object
emp_id object
dtype: object
1.2、size、ndim和 shape属性的使用
# 查看DataFrame的元素个数
print('订单详情表的元素个数为:', detail.size)
print('订单详情表的维度数为:', detail.ndim) # 查看DataFrame的维度数
print('订单详情表的形状为:', detail.shape) # 查看DataFrame的形状
订单详情表的元素个数为: 52801
订单详情表的维度数为: 2
订单详情表的形状为: (2779, 19)
1.3、使用T属性进行转置
print('订单详情表转置前形状为:', detail.shape)
print('订单详情表转置后形状为为:', detail.T.shape)
订单详情表转置前形状为: (2779, 19)
订单详情表转置后形状为为: (19, 2779)
二、查改增删DataFrame数据
2.1、查看访问DataFrame中的数据
2.1.1、使用字典访问内部数据的方式访问DataFrame单列数据
# 使用访问字典方式取出orderInfo中的某一列
order_id = detail['order_id']
print('订单详情表中的order_id的形状为:', '\n', order_id.shape)
订单详情表中的order_id的形状为:
(2779,)
2.1.2、使用访问属性的方式访问DataFrame单列数据
# 使用访问属性方式取出orderInfo中的菜品名称列
dishes_name = detail.dishes_name
print('订单详情表中的dishes_name的形状为:', dishes_name.shape)
订单详情表中的dishes_name的形状为: (2779,)
2.1.3、DataFrame单列多行数据获取
dishes_name5 = detail['dishes_name'][:5]
print('订单详情表中的dishes_name前5个元素为:', '\n', dishes_name5)
订单详情表中的dishes_name前5个元素为:
0 蒜蓉生蚝
1 蒙古烤羊腿
2 大蒜苋菜
3 芝麻烤紫菜
4 蒜香包
Name: dishes_name, dtype: object
2.1.4、访问DataFrame多列的多行数据
orderDish = detail[['order_id', 'dishes_name']][:5]
print('订单详情表中的order_id和dishes_name前5个元素为:',
'\n', orderDish)
订单详情表中的order_id和dishes_name前5个元素为:
order_id dishes_name
0 417 蒜蓉生蚝
1 417 蒙古烤羊腿
2 417 大蒜苋菜
3 417 芝麻烤紫菜
4 417 蒜香包
2.1.5、访问DataFrame多行数据
order5 = detail[:][1:6]
print('订单详情表的1-5行元素为:', '\n', order5)
订单详情表的1-5行元素为:
detail_id order_id dishes_id logicprn_name parent_class_name dishes_name \
1 2958 417 609957 NA NA 蒙古烤羊腿
2 2961 417 609950 NA NA 大蒜苋菜
3 2966 417 610038 NA NA 芝麻烤紫菜
4 2968 417 610003 NA NA 蒜香包
5 1899 301 610019 NA NA 白斩鸡
itemis_add counts amounts cost place_order_time discount_amt \
1 0 1.0 48.0 NA 2016-08-01 11:07:00 NA
2 0 1.0 30.0 NA 2016-08-01 11:07:00 NA
3 0 1.0 25.0 NA 2016-08-01 11:11:00 NA
4 0 1.0 13.0 NA 2016-08-01 11:11:00 NA
5 0 1.0 88.0 NA 2016-08-01 11:15:00 NA
discount_reason kick_back add_inprice add_info bar_code picture_file \
1 NA NA 0 NA NA caipu/202003.jpg
2 NA NA 0 NA NA caipu/303001.jpg
3 NA NA 0 NA NA caipu/105002.jpg
4 NA NA 0 NA NA caipu/503002.jpg
5 NA NA 0 NA NA caipu/204002.jpg
emp_id
1 1442
2 1442
3 1442
4 1442
5 1095
2.1.6、使用DataFrame的head和tail方法获取多行数据
print('订单详情表中前五行数据为', '\n', detail.head())
print('订单详情表中后五个元素为:', '\n', detail.tail())
订单详情表中前五行数据为
detail_id order_id dishes_id logicprn_name parent_class_name dishes_name \
0 2956 417 610062 NA NA 蒜蓉生蚝
1 2958 417 609957 NA NA 蒙古烤羊腿
2 2961 417 609950 NA NA 大蒜苋菜
3 2966 417 610038 NA NA 芝麻烤紫菜
4 2968 417 610003 NA NA 蒜香包
itemis_add counts amounts cost place_order_time discount_amt \
0 0 1.0 49.0 NA 2016-08-01 11:05:00 NA
1 0 1.0 48.0 NA 2016-08-01 11:07:00 NA
2 0 1.0 30.0 NA 2016-08-01 11:07:00 NA
3 0 1.0 25.0 NA 2016-08-01 11:11:00 NA
4 0 1.0 13.0 NA 2016-08-01 11:11:00 NA
discount_reason kick_back add_inprice add_info bar_code picture_file \
0 NA NA 0 NA NA caipu/104001.jpg
1 NA NA 0 NA NA caipu/202003.jpg
2 NA NA 0 NA NA caipu/303001.jpg
3 NA NA 0 NA NA caipu/105002.jpg
4 NA NA 0 NA NA caipu/503002.jpg
emp_id
0 1442
1 1442
2 1442
3 1442
4 1442
订单详情表中后五个元素为:
detail_id order_id dishes_id logicprn_name parent_class_name dishes_name \
2774 6750 774 610011 NA NA 白饭/大碗
2775 6742 774 609996 NA NA 牛尾汤
2776 6756 774 609949 NA NA 意文柠檬汁
2777 6763 774 610014 NA NA 金玉良缘
2778 6764 774 610017 NA NA 酸辣藕丁
itemis_add counts amounts cost place_order_time discount_amt \
2774 0 1.0 10.0 NA 2016-08-10 21:56:00 NA
2775 0 1.0 40.0 NA 2016-08-10 21:56:00 NA
2776 0 1.0 13.0 NA 2016-08-10 22:01:00 NA
2777 0 1.0 30.0 NA 2016-08-10 22:03:00 NA
2778 0 1.0 33.0 NA 2016-08-10 22:04:00 NA
discount_reason kick_back add_inprice add_info bar_code \
2774 NA NA 0 NA NA
2775 NA NA 0 NA NA
2776 NA NA 0 NA NA
2777 NA NA 0 NA NA
2778 NA NA 0 NA NA
picture_file emp_id
2774 caipu/601005.jpg 1138
2775 caipu/201006.jpg 1138
2776 caipu/404005.jpg 1138
2777 caipu/302003.jpg 1138
2778 caipu/302006.jpg 1138
2.1.7、使用loc和iloc 实现单列切片
dishes_name1 = detail.loc[:, 'dishes_name']
print('使用loc提取dishes_name列的size为:', dishes_name1.size)
dishes_name2 = detail.iloc[:, 3]
print('使用iloc提取第3列的size为:', dishes_name2.size)
使用loc提取dishes_name列的size为: 2779
使用iloc提取第3列的size为: 2779
2.1.8、使用 loc、iloc 实现多列切片
orderDish1 = detail.loc[:, ['order_id', 'dishes_name']]
print('使用loc提取order_id和dishes_name列的size为:',
orderDish1.size)
orderDish2 = detail.iloc[:, [1, 3]]
print('使用iloc提取第1和第3列的size为:', orderDish2.size)
使用loc提取order_id和dishes_name列的size为: 5558
使用iloc提取第1和第3列的size为: 5558
2.1.9、使用loc、iloc 实现花式切片
print('列名为order_id和dishes_name的行名为3的数据为:\n',
detail.loc[3, ['order_id', 'dishes_name']])
print('列名为order_id和dishes_name行名为2,3,4,5,6的数据为:\n',
detail.loc[2:6, ['order_id', 'dishes_name']])
print('列位置为1和3行位置为3的数据为:\n', detail.iloc[3, [1, 3]])
print('列位置为1和3行位置为2,3,4,5,6的数据为:\n',
detail.iloc[2:7, [1, 3]])
列名为order_id和dishes_name的行名为3的数据为:
order_id 417
dishes_name 芝麻烤紫菜
Name: 3, dtype: object
列名为order_id和dishes_name行名为2,3,4,5,6的数据为:
order_id dishes_name
2 417 大蒜苋菜
3 417 芝麻烤紫菜
4 417 蒜香包
5 301 白斩鸡
6 301 香烤牛排
列位置为1和3行位置为3的数据为:
order_id 417
logicprn_name NA
Name: 3, dtype: object
列位置为1和3行位置为2,3,4,5,6的数据为:
order_id logicprn_name
2 417 NA
3 417 NA
4 417 NA
5 301 NA
6 301 NA
2.1.10、使用loc和iloc 实现条件切片
# loc内部传入表达式
print('detail中order_id为458的dishes_name为:\n',
detail.loc[detail['order_id'] == '458',
['order_id', 'dishes_name']])
detail中order_id为458的dishes_name为:
order_id dishes_name
145 458 蒜香辣花甲
146 458 剁椒鱼头
147 458 凉拌蒜蓉西兰花
148 458 木须豌豆
149 458 辣炒鱿鱼
150 458 酸辣藕丁
151 458 炝炒大白菜
152 458 香菇鸡肉粥
153 458 干锅田鸡
154 458 桂圆枸杞鸽子汤
155 458 五香酱驴肉
156 458 路易拉菲红酒干红
157 458 避风塘炒蟹
158 458 白饭/大碗
print('detail中order_id为458的第1,5列数据为:\n',
detail.iloc[detail['order_id'] == '458', [1, 5]])
NotImplementedError: iLocation based boolean indexing on an integer type is not available
此处的 iloc方法不能接收表达式,原因在于,此处条件返回的为一个布尔值 Series,而iloc可以接收的数据类型并不包括Series。根据Series的构成,只要取出该Series的 values就可以了。
2.1.11、使用iloc 实现条件切片
print('detail中order_id为458的第1,5列数据为:\n',
detail.iloc[(detail['order_id'] == '458').values, [1, 5]])
detail中order_id为458的第1,5列数据为:
order_id dishes_name
145 458 蒜香辣花甲
146 458 剁椒鱼头
147 458 凉拌蒜蓉西兰花
148 458 木须豌豆
149 458 辣炒鱿鱼
150 458 酸辣藕丁
151 458 炝炒大白菜
152 458 香菇鸡肉粥
153 458 干锅田鸡
154 458 桂圆枸杞鸽子汤
155 458 五香酱驴肉
156 458 路易拉菲红酒干红
157 458 避风塘炒蟹
158 458 白饭/大碗
2.1.12、使用loc、iloc、ix实现切片比较
print('列名为dishes_name行名为2,3,4,5,6的数据为:\n',
detail.loc[2:6, 'dishes_name'])
print('列位置为5,行位置为2至6的数据为:\n', detail.iloc[2:6, 5])
print('列位置为5行名为2至6的数据为:', '\n', detail.ix[2:6, 5])
列名为dishes_name行名为2,3,4,5,6的数据为:
2 大蒜苋菜
3 芝麻烤紫菜
4 蒜香包
5 白斩鸡
6 香烤牛排
Name: dishes_name, dtype: object
列位置为5,行位置为2至6的数据为:
2 大蒜苋菜
3 芝麻烤紫菜
4 蒜香包
5 白斩鸡
Name: dishes_name, dtype: object
列位置为5行名为2至6的数据为:
2 大蒜苋菜
3 芝麻烤紫菜
4 蒜香包
5 白斩鸡
6 香烤牛排
Name: dishes_name, dtype: object
2.2、更改DataFrame 中的数据
# 将order_id为458的,变换为45800
detail.loc[detail['order_id'] == '458', 'order_id'] = '45800'
print('更改后detail中order_id为458的order_id为:\n',
detail.loc[detail['order_id'] == '458', 'order_id'])
print('更改后detail中order_id为45800的order_id为:\n',
detail.loc[detail['order_id'] == '45800', 'order_id'])
更改后detail中order_id为458的order_id为:
Series([], Name: order_id, dtype: object)
更改后detail中order_id为45800的order_id为:
145 45800
146 45800
147 45800
148 45800
149 45800
150 45800
151 45800
152 45800
153 45800
154 45800
155 45800
156 45800
157 45800
158 45800
Name: order_id, dtype: object
2.3、为DataFrame增添数据
2.3.1、为DataFrame新增一列非定值
detail['payment'] = detail['counts'] * detail['amounts']
print('detail新增列payment的前五行为:', '\n',
detail['payment'].head())
detail新增列payment的前五行为:
0 49.0
1 48.0
2 30.0
3 25.0
4 13.0
Name: payment, dtype: float64
2.3.2、为DataFrame新增一列定值
detail['pay_way'] = '现金支付'
print('detail新增列pay_way的前五行为:', '\n',
detail['pay_way'].head())
detail新增列pay_way的前五行为:
0 现金支付
1 现金支付
2 现金支付
3 现金支付
4 现金支付
Name: pay_way, dtype: object
2.4、删除某列或某行数据
2.4.1、删除 DataFrame某列
print('删除pay_way前deatil的列索引为:', '\n', detail.columns)
detail.drop(labels='pay_way', axis=1, inplace=True)
print('删除pay_way后detail的列索引为:', '\n', detail.columns)
删除pay_way前deatil的列索引为:
Index(['detail_id', 'order_id', 'dishes_id', 'logicprn_name',
'parent_class_name', 'dishes_name', 'itemis_add', 'counts', 'amounts',
'cost', 'place_order_time', 'discount_amt', 'discount_reason',
'kick_back', 'add_inprice', 'add_info', 'bar_code', 'picture_file',
'emp_id', 'payment', 'pay_way'],
dtype='object')
删除pay_way后detail的列索引为:
Index(['detail_id', 'order_id', 'dishes_id', 'logicprn_name',
'parent_class_name', 'dishes_name', 'itemis_add', 'counts', 'amounts',
'cost', 'place_order_time', 'discount_amt', 'discount_reason',
'kick_back', 'add_inprice', 'add_info', 'bar_code', 'picture_file',
'emp_id', 'payment'],
dtype='object')
2.4.2、删除 DataFrame某几行
print('删除1-10行前detail的长度为:', len(detail))
detail.drop(labels=range(1, 11), axis=0, inplace=True)
print('删除1-10行后detail的列索引为:', len(detail))
删除1-10行前detail的长度为: 2779
删除1-10行后detail的列索引为: 2769
三、描述分析DataFrame数据
3.1、数值型特征的描述性统计
3.1.1、代码使用np.mean函数计算平均价格
import numpy as np
print('订单详情表中amount(价格)的平均值为:', np.mean(detail['amounts']))
订单详情表中amount(价格)的平均值为: 45.343084145901045
3.1.2、通过pandas 计算平均价格
print('订单详情表中amount(价格)的平均值为:', detail['amounts'].mean())
订单详情表中amount(价格)的平均值为: 45.343084145901045
3.1.3、使用describe方法实现数值型特征的描述性统计
print('订单详情表counts和amounts两列的描述性统计为:\n',
detail[['counts', 'amounts']].describe())
订单详情表counts和amounts两列的描述性统计为:
counts amounts
count 2769.000000 2769.000000
mean 1.111593 45.343084
std 0.626521 36.841316
min 1.000000 1.000000
25% 1.000000 25.000000
50% 1.000000 35.000000
75% 1.000000 56.000000
max 10.000000 178.000000
3.2、类别型特征的描述性统计
3.2.1、对菜品名称频数统计
print('订单详情表dishes_name频数统计结果前10为:\n',
detail['dishes_name'].value_counts()[0:10])
订单详情表dishes_name频数统计结果前10为:
白饭/大碗 91
凉拌菠菜 77
谷稻小庄 72
麻辣小龙虾 65
白饭/小碗 60
五色糯米饭(七色) 58
焖猪手 55
芝士烩波士顿龙虾 55
辣炒鱿鱼 53
水煮鱼 47
Name: dishes_name, dtype: int64
3.2.2、将object 数据强制转换为category类型
detail['dishes_name'] = detail['dishes_name'].astype('category')
print('订单信息表dishes_name列转变数据类型后为:', detail['dishes_name'].dtypes)
订单信息表dishes_name列转变数据类型后为: category
3.2.3、category类型特征的描述性统计
print('订单信息表dishes_name的描述统计结果为:\n',
detail['dishes_name'].describe())
订单信息表dishes_name的描述统计结果为:
count 2769
unique 145
top 白饭/大碗
freq 91
Name: dishes_name, dtype: object
四、案例操作
4.1、查看餐饮数据的大小和维度
from sqlalchemy import create_engine
import pandas as pd
engine = create_engine('mysql+pymysql://root:1234@127.0.0.1:\
3306/testdb?charset=utf8')
detail = pd.read_sql_table('meal_order_detail1',
con=engine)
order = pd.read_table('../data/meal_order_info.csv',
sep=',', encoding='gbk')
user = pd.read_excel('../data/users.xlsx')
print('订单详情表的维度为:', detail.ndim)
print('订单信息表的维度为:', order.ndim)
print('客户信息表的维度为:', user.ndim)
print('订单详情表的形状为:', detail.shape)
print('订单信息表的形状为:', order.shape)
print('客户信息表的形状为:', user.shape)
print('订单详情表的元素个数为:', detail.size)
print('订单信息表的元素个数为:', order.size)
print('客户信息表的元素个数为:', user.size)
订单详情表的维度为: 2
订单信息表的维度为: 2
客户信息表的维度为: 2
订单详情表的形状为: (2779, 19)
订单信息表的形状为: (945, 21)
客户信息表的形状为: (734, 37)
订单详情表的元素个数为: 52801
订单信息表的元素个数为: 19845
客户信息表的元素个数为: 27158
4.2、统计餐饮菜品销售状况
print('订单详情表counts和amounts两列的描述性统计为:\n',
detail.loc[:, ['counts', 'amounts']].describe())
detail['order_id'] = detail['order_id'].astype('category')
detail['dishes_name'] = detail['dishes_name'].astype('category')
print('''订单信息表order_id(订单编号)与dishes_name(菜品名称)
的描述性统计结果为:''', '\n',
detail[['order_id', 'dishes_name']].describe())
订单详情表counts和amounts两列的描述性统计为:
counts amounts
count 2779.000000 2779.000000
mean 1.111191 45.337172
std 0.625428 36.808550
min 1.000000 1.000000
25% 1.000000 25.000000
50% 1.000000 35.000000
75% 1.000000 56.000000
max 10.000000 178.000000
订单信息表order_id(订单编号)与dishes_name(菜品名称)
的描述性统计结果为:
order_id dishes_name
count 2779 2779
unique 278 145
top 392 白饭/大碗
freq 24 92
4.3、剔除全为空值或者所有元素取值相同的列
# 定义一个函数去除全为空值的列和标准差为0的列
def dropNullStd(data):
beforelen = data.shape[1]
colisNull = data.describe().loc['count'] == 0
for i in range(len(colisNull)):
if colisNull[i]:
data.drop(colisNull.index[i], axis=1, inplace=True)
stdisZero = data.describe().loc['std'] == 0
for i in range(len(stdisZero)):
if stdisZero[i]:
data.drop(stdisZero.index[i], axis=1, inplace=True)
afterlen = data.shape[1]
print('去除的列的数目为:', beforelen - afterlen)
print('去除后数据的形状为:', data.shape)
dropNullStd(detail)
# 使用dropNullStd函数对订单信息表操作
dropNullStd(order)
# 使用dropNullStd函数对客户信息表操作
dropNullStd(user)
去除的列的数目为: 0
去除后数据的形状为: (2779, 19)
去除的列的数目为: 7
去除后数据的形状为: (945, 14)
去除的列的数目为: 13
去除后数据的形状为: (734, 24)