一、Pandas介绍

1、介绍

pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。Pandas 纳入了大量库和一些标准的数据模型,提供了高效地操作大型数据集所需的工具。pandas提供了大量能使我们快速便捷地处理数据的函数和方法。你很快就会发现,它是使Python成为强大而高效的数据分析环境的重要因素之一。

2、数据结构

Series:一维数组,与Numpy中的一维array类似。二者与Python基本的数据结构List也很相近。Series如今能保存不同种数据类型,字符串、boolean值、数字等都能保存在Series中。
Time- Series:以时间为索引的Series。
DataFrame:二维的表格型数据结构。很多功能与R中的data.frame类似。可以将DataFrame理解为Series的容器。
Panel :三维的数组,可以理解为DataFrame的容器。

二、Pandas数据结构之Series

import pandas as pd
from pandas import Series,DataFrame
import numpy as np

Series是一种类似与一维数组的对象,由下面两个部分组成:

  • values:一组数据(ndarray类型)
  • index:相关的数据索引标签

1、Series的创建

# 有两种创建方式
# 1.由列表或numpy数组创建(默认索引为0到N-1的整数型索引) # 使用列表创建Series
Series(data=[1,2,3,4,5],name='zzz')
# 结果
0 1
1 2
2 3
3 4
4 5
Name: zzz, dtype: int64 # 使用numpy创建Series
Series(data=np.random.randint(0,10,size=(5,)))
# 结果
0 7
1 6
2 2
3 2
4 2
dtype: int32 # 还可以通过设置index参数指定索引
s = Series(data=np.random.randint(0,10,size=(5,)),index=['a','b','c','d','e'])
# 结果
a 2
b 5
c 6
d 6
e 3
dtype: int32 # 2.由字典创建:不能再使用index.但是依然存在默认索引
# 注意:数据源必须为一维数据
dic = {
'语文':80,
'数学':95
}
s = Series(data=dic)
# 结果
数学 95
语文 80
dtype: int64

2、Series的索引

可以使用中括号取单个索引(此时返回的是元素类型),或者中括号里一个列表取多个索引(此时返回的是一个Series类型)。

(1) 显式索引:

- 使用index中的元素作为索引值
- 使用s.loc[](推荐):注意,loc中括号中放置的一定是显示索引

注意,此时是闭区间

(2) 隐式索引:

- 使用整数作为索引值
- 使用.iloc[](推荐):iloc中的中括号中必须放置隐式索引

注意,此时是半开区间

s = Series(data=np.random.randint(0,10,size=(5,)),index=['a','b','c','d','e'])

# s的值
a 7
b 6
c 3
d 1
e 8
dtype: int32 # 隐式索引
s[0]
# 结果
7 s[[0,1]]
# 结果
a 7
b 6
dtype: int32 s.iloc[0]
# 结果
7 s.iloc[[0,1]]
# 结果
a 7
b 6
dtype: int32 # 显示索引
s.a
# 结果
7 s[['a','d']]
# 结果
a 7
d 1
dtype: int32 s.loc['a']
# 结果
7 s.loc[['a','b']]
# 结果
a 7
b 6
dtype: int32

3、切片

# 1.显示索引切片:index和loc
s = Series(data=np.random.randint(0,10,size=(5,)),index=['a','b','c','d','e'])
a 5
b 7
c 6
d 0
e 0
dtype: int32 s['a':'d']
# 结果
a 5
b 7
c 6
d 0
dtype: int32 s.loc['a':'c']
# 结果
a 5
b 7
c 6
dtype: int32 # 2.隐式索引切片:整数索引值和iloc
s[0:3]
# 结果
a 5
b 7
c 6
dtype: int32 s.iloc[0:3]
# 结果
a 5
b 7
c 6
dtype: int32

4、Series的基本概念

可以把Series看成一个不定长的有序字典

s = Series(data=np.random.randint(0,10,size=(5,)),index=['a','b','c','d','e'])
a 5
b 7
c 6
d 0
e 0
dtype: int32 # 1.向Series增加一行:相当于给字典增加一组键值对
s['g'] = 10
# 结果
a 5
b 7
c 6
d 0
e 0
g 10
dtype: int64 # 2.可以通过shape,size,index,values等得到series的属性
s.shape # (6,) s.size # s.index # Index(['a', 'b', 'c', 'd', 'e', 'g'], dtype='object') s.values # array([ 5, 7, 6, 0, 0, 10], dtype=int64) # 3.可以使用s.head(),tail()分别查看前n个和后n个值
s.head(3)
a 5
b 7
c 6
dtype: int64 s.tail(2)
e 0
g 10
dtype: int64 # 4.对Series元素进行去重
s = Series([1,1,1,2,2,3,3,4,4,4,5,6,6])
0 1
1 1
2 1
3 2
4 2
5 3
6 3
7 4
8 4
9 4
10 5
11 6
12 6
dtype: int64 s.unique() # 使用unique去重,返回的是一个ndarray
array([1, 2, 3, 4, 5, 6], dtype=int64) # 5.当索引没有对应的值时,可能出现缺失数据显示NaN(not a number)的情况
s1 = Series([1,2,3],index=['a','b','c'])
s2 = Series([1,2,3],index=['a','b','d'])
display(s1,s2)
a 1
b 2
c 3
dtype: int64 a 1
b 2
d 3
dtype: int64 # 让两个Series进行相加
s = s1+s2
a 2.0
b 4.0
c NaN
d NaN
dtype: float64 # 6.可以使用pd.isnull(),pd.notnull(),或s.isnull(),notnull()函数检测缺失数据
# 上面相加后的s
s.isnull()
a False
b False
c True
d True
dtype: bool s.notnull()
a True
b True
c False
d False
dtype: bool # 把缺失的数据去掉
s[[True,True,False,False]] # 保留的True
a 2.0
b 4.0
dtype: float64 # 或者可以使用notnull
s[s.notnull()]
a 2.0
b 4.0
dtype: float64 # 7.Series的运算
'''
Series之间的运算
在运算中自动对齐不同索引的数据
如果索引不对应,则补NaN 运算法则:
+ - * / 相当于 add() sub() mul() div()
''' s1 = Series([1,2,3])
s2 = Series([4,5,6]) # 加法
s1+s2 # s1.add(s2)
0 5
1 7
2 9
dtype: int64 # 乘法
s1.mul(s2) # s1 * s2
0 4
1 10
2 18
dtype: int64

三、Pandas数据结构之DataFrame

DataFrame是一个【表格型】的数据结构。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。

  • 行索引:index
  • 列索引:columns
  • 值:values

1、DataFrame的创建

最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。

此外,DataFrame会自动加上每一行的索引。

使用字典创建的DataFrame后,则columns参数将不可被使用。

同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。

  • 使用字典创建DataFrame
import pandas as pd
from pandas import Series,DataFrame
import numpy as np dic = {
'name':['john','tom'],
'salary':[10000,20000]
} # 字典的键即列名,使用index可以设置行名
df = DataFrame(data=dic,index=['a','b'])
# 结果
name salary
a john 10000
b tom 20000 # 如果不指定index行名,则使用默认的隐式索引
df = DataFrame(data=dic)
# 结果
name salary
0 john 10000
1 tom 20000
  • 使用ndarray创建DataFrame
np.random.seed(1)

# 不指定index和columns,则使用默认隐式索引
DataFrame(data=np.random.randint(0,100,size=(3,4)))
# 结果
0 1 2 3
0 37 12 72 9
1 75 5 79 64
2 16 1 76 71 # 指定index
DataFrame(data=np.random.randint(0,100,size=(3,4)),index=['a','b','c'])
# 结果
0 1 2 3
a 37 12 72 9
b 75 5 79 64
c 16 1 76 71 # 指定index和columns
DataFrame(data=np.random.randint(0,100,size=(3,4)),index=['a','b','c'],columns=['A','B','C','D'])
# 结果
A B C D
a 37 12 72 9
b 75 5 79 64
c 16 1 76 71
  • DataFrame属性:values、columns、index、shape
dic = {
'name':['john','tom'],
'salary':[10000,20000]
} df = DataFrame(data=dic)
# df
name salary
0 john 10000
1 tom 20000 # df的值
df.values
# 结果
array([['john', 10000],
['tom', 20000]], dtype=object) # df的列索引
df.columns
# 结果
Index(['name', 'salary'], dtype='object') # df的行索引
df.index
# 结果
RangeIndex(start=0, stop=2, step=1) # df的维度(形状)
df.shape
# 结果
(2, 2)

2、DataFrame的索引

(1) 对列进行索引

- 通过类似字典的方式  df['q']
- 通过属性的方式 df.q

可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。

dic = {
'张三':[150,150,150,300],
'李四':[0,0,0,0]
} df = DataFrame(data=dic,index=['语文','数学','英语','理综'])
# df 张三 李四
语文 150 0
数学 150 0
英语 150 0
理综 300 0 # 1.修改列索引
df.columns = ['zhangsan','lisi']
# 结果
zhangsan lisi
语文 150 0
数学 150 0
英语 150 0
理综 300 0 # 2.获取zhangsan这列数据
df['zhangsan']
# 结果
语文 150
数学 150
英语 150
理综 300
Name: zhangsan, dtype: int64 # 3.获取lisi这列数据
df.lisi
# 结果
语文 0
数学 0
英语 0
理综 0
Name: lisi, dtype: int64 # 4.获取前两列
df[['lisi','zhangsan']]
# 结果
lisi zhangsan
语文 0 150
数学 0 150
英语 0 150
理综 0 300

(2) 对行进行索引

- 使用.loc[]加index来进行行索引
- 使用.iloc[]加整数来进行行索引
- 使用.loc[行]:默认输出这行所有内容
- 使用.loc[行,列]:找到这行的某一列,定位到某行的某个值

同样返回一个Series,index为原来的columns。

# df
zhangsan lisi
语文 150 0
数学 150 0
英语 150 0
理综 300 0 # 1.获取显示索引为数学的成绩
df.loc['数学']
# 结果
zhangsan 150
lisi 0
Name: 数学, dtype: int64 # 2.获取隐式索引为1的成绩
df.iloc[1]
# 结果
zhangsan 150
lisi 0
Name: 数学, dtype: int64

(3) 对元素索引的方法

- 使用列索引
- 使用行索引(iloc[3,1] or loc['C','q']) 行索引在前,列索引在后,定位到某个行某个元素
# df
zhangsan lisi
语文 150 0
数学 150 0
英语 150 0
理综 300 0 # 1.获取英语成绩且是张三的成绩
df.loc['英语','zhangsan']
# 结果
150

# 获取张三的语文和数学成绩
df.loc[['语文','数学'],'zhangsan']
# 结果
语文 150
数学 150
Name:zhangsan, dtype:int64 # 2.修改张三的英语成绩
df.loc['英语','zhangsan'] = 60
# 结果
zhangsan lisi
语文 150 0
数学 150 0
英语 60 0
理综 300 0

(3) 切片

【注意】 直接用中括号时:

  • 索引表示的是列索引
  • 切片表示的是行切片
# df
zhangsan lisi
语文 150 0
数学 150 0
英语 60 0
理综 300 0 # 1.获取语文到英语这些行的数据
df['语文':'英语']
# 结果
zhangsan lisi
语文 150 0
数学 150 0
英语 60 0 # 2.在loc和iloc中使用切片(切列): df.loc['B':'C','丙':'丁']
df.loc['数学':'英语','zhangsan':'lisi']
# 结果
zhangsan lisi
数学 150 0
英语 60 0

3、DataFrame的运算

(1) DataFrame之间的运算

同Series一样:

  • 在运算中自动对齐不同索引的数据
  • 如果索引不对应,则补NaN
# df
zhangsan lisi
语文 150 0
数学 150 0
英语 60 0
理综 300 0 # 1.加法
df + df
# 结果
zhangsan lisi
语文 300 0
数学 300 0
英语 120 0
理综 600 0 # 2.除法
df / df
# 结果 zhangsan lisi
语文 1.0 NaN
数学 1.0 NaN
英语 1.0 NaN
理综 1.0 NaN # 3.把张三的数学成绩改成0分
df.loc['数学','zhangsan'] = 0
# 结果
   zhangsan lisi
语文 150 0
数学 0 0
英语 60 0
理综 300 0 # 4.把李四所有成绩改成100分
df['lisi'] += 100
# 结果
   zhangsan lisi
语文 150 100
数学 0 100
英语 60 100
理综 300 100 # 5.把所有人的成绩都加10分
df += 10
# 结果
   zhangsan lisi
语文 160 110
数学 10 110
英语 70 110
理综 310 110

四、处理丢失的数据

panda之数据加载

read_xxx()参数:

- sep
-header
# 常用的数据加载方式
pd.read_csv()
pd.read_excel()
pd.read_sql

1、两种丢失的数据

有两种丢失数据:

  • None
  • np.nan(NaN)
# 1.None
None是Python自带的,其类型为python object。因此,None不能参与到任何计算中。 # 查看None的数据类型
type(None) # NoneType # 2.np.nan(NaN)
np.nan是浮点类型,能参与到计算中。但计算的结果总是NaN。 # 查看np.nan的数据类型
type(np.nan) # float
np.nan + 1 # nan

2、pandas中的None与NaN

  • pandas中None与np.nan都视作np.nan

(1)数据的准备

# 1.创建DataFrame
np.random.seed(1)
df = DataFrame(np.random.randint(100,200,size=(7,6)))
# 结果
0 1 2 3 4 5
0 137 112 172 109 175 105
1 179 164 116 101 176 171
2 106 125 150 120 118 184
3 111 128 129 114 150 168
4 187 187 194 196 186 113
5 109 107 163 161 122 157
6 101 100 160 181 108 188 # 2.将某些数组元素赋值为nan
df.iloc[1,2] = None
df.iloc[3,2] = np.nan
df.iloc[4,4] = None
# 结果 0 1 2 3 4 5
0 137 112 172.0 109 175.0 105
1 179 164 NaN 101 176.0 171
2 106 125 150.0 120 118.0 184
3 111 128 NaN 114 150.0 168
4 187 187 194.0 196 NaN 113
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188

(2)pandas处理空值操作

  • isnull():  判断函数
  • notnull():判断函数
  • dropna(): 过滤丢失数据
  • fillna(): 填充丢失数据

(2-1)判断函数和删除函数

  • isnull()
  • notnull()
  • drop()
# 1.判断函数
isnull()
notnull() # df
   0 1 2 3 4 5
0 137 112 172.0 109 175.0 105
1 179 164 NaN 101 176.0 171
2 106 125 150.0 120 118.0 184
3 111 128 NaN 114 150.0 168
4 187 187 194.0 196 NaN 113
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188 # 判断是否为空
df.isnull()
# 结果
0 1    2    3    4   5
0 False False False False False False
1 False False True False False False
2 False False False False False False
3 False False True False False False
4 False False False False True False
5 False False False False False False
6 False False False False False False # 2.清洗数据函数drop
  drop() # 使用drop进行数据的清洗
# df.drop(labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')
drop删除数据
指定删除
df.drop(labels=1)删除行索引为1的数据,删除多行用labels=[0,1,2]
df.drop(columns=1)删除列索引为1的数据,删除多列用columns=[1,2,3] 当没有指定labels或者columns时候,axis=0代表行,axis=1代表列,不写,默认是行
df.drop([0, 1])相当于df.drop([0, 1], axis=0) 删除行索引为0和1的数据
df.drop([0, 1], axis=1) 删除列索引为0和1的数据 # 删除行索引为1的数据
df.drop(labels=1)
# 结果
0 1 2 3 4 5
0 137 112 172.0 109 175.0 105
2 106 125 150.0 120 118.0 184
3 111 128 NaN 114 150.0 168
4 187 187 194.0 196 NaN 113
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188 # 只保留True的行,即0和2行的数据
df.loc[[True,False,True]]
# 结果
0 1 2 3 4 5
0 137 112 172.0 109 175.0 105
2 106 125 150.0 120 118.0 184

(2-2)判断函数和any/all的结合使用

  • df.notnull/isnull().any()/all()
# 1.isnull是否是空值
df.isnull()
# 结果
     0   1    2    3   4    5
0 False False False False False False
1 False False True False False False
2 False False False False False False
3 False False True False False False
4 False False False False True False
5 False False False False False False
6 False False False False False False # any查看各行是否含有空值
# axis=0代表列,axis=1代表行
df.isnull().any(axis=1)
0 False # 代表索引为0的这行没有空值
1 True # 代表索引为1的这行有空值
2 False
3 True
4 True
5 False
6 False
dtype: bool # 共多少行含有空值
df.isnull().any(axis=1).sum()
# 结果
3 # 代表df中一共有3行数据里面含有空值 # 返回含有空值的行
df.loc[df.isnull().any(axis=1)]
# 结果
    0 1 2 3 4 5
1 179 164 NaN 101 176.0 171
3 111 128 NaN 114 150.0 168
4 187 187 194.0 196 NaN 113 # 返回含有空值的行的索引
index = df.loc[df.isnull().any(axis=1)].index
# 结果
Int64Index([1, 3, 4], dtype='int64') # 删除含有空白行的数据
df.drop(labels=index)
# 结果
    0  1   2   3   4 5
0 137 112 172.0 109 175.0 105
2 106 125 150.0 120 118.0 184
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188 # all查看各行是否全部都是空值
df.isnull().all(axis=1)
0 False
1 False
2 False
3 False
4 False
5 False
6 False
dtype: bool # 2.notnull是否不是空值
df.notnull()
# 结果
  0   1 2 3 4 5
0 True True True True True True
1 True True False True True True
2 True True True True True True
3 True True False True True True
4 True True True True False True
5 True True True True True True
6 True True True True True True # all查看各行是否全部都不是空值
df.notnull().all(axis=1)
0 True
1 False
2 True
3 False
4 False
5 True
6 True
dtype: bool # 把全部都不是空值的行输出
df.loc[df.notnull().all(axis=1)]
# 结果
    0 1 2 3 4   5
0 137 112 172.0 109 175.0 105
2 106 125 150.0 120 118.0 184
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188

(2-3)判断函数和any/all的结合使用

  • df.dropna(): 过滤空值的行/列
df.dropna() 可以选择过滤的是行还是列(默认为行):axis中0表示行,1表示的列

# 1.过滤含有空值的行
df.dropna(axis=0)
# 结果
0 1 2 3 4 5
0 137 112 172.0 109 175.0 105
2 106 125 150.0 120 118.0 184
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188 # 2.过滤含有空值的列
df.dropna(axis=1)
# 结果
0 1 3 5
0 137 112 109 105
1 179 164 101 171
2 106 125 120 184
3 111 128 114 168
4 187 187 196 113
5 109 107 161 157
6 101 100 181 188

(2-4) 填充函数 Series/DataFrame

  • fillna():value和method参数
df.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)

# df
    0 1 2 3 4 5
0 137 112 172.0 109 175.0 105
1 179 164 NaN 101 176.0 171
2 106 125 150.0 120 118.0 184
3 111 128 NaN 114 150.0 168
4 187 187 194.0 196 NaN 113
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188 # 1.用value填充空值
df.fillna(value=0) 等于 df.fillna(0) # 用0填充所有空值
# 结果
    0 1 2 3 4 5
0 137 112 172.0 109 175.0 105
1 179 164 0.0 101 176.0 171
2 106 125 150.0 120 118.0 184
3 111 128 0.0 114 150.0 168
4 187 187 194.0 196 0.0 113
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188 # 2.将索引为2和4的列的空值分别替换成1和2
values = {2: 1, 4: 2}
df.fillna(value=values) # df.fillna(value=values, limit=1) 代表只替换2和4列的第一个空值
# 结果
    0 1 2 3 4 5
0 137 112 172.0 109 175.0 105
1 179 164 1.0 101 176.0 171
2 106 125 150.0 120 118.0 184
3 111 128 1.0 114 150.0 168
4 187 187 194.0 196 2.0 113
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188 # 3.前向填充,用axis指定列还是行,0代表列,1代表行
df.fillna(method='ffill',axis=0)
# 结果
    0 1 2 3 4 5
0 137 112 172.0 109 175.0 105
1 179 164 172.0 101 176.0 171
2 106 125 150.0 120 118.0 184
3 111 128 150.0 114 150.0 168
4 187 187 194.0 196 150.0 113
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188 # 4.后向填充
df.fillna(method='bfill',axis=0)
# 结果
0 1 2 3 4 5
0 137 112 172.0 109 175.0 105
1 179 164 150.0 101 176.0 171
2 106 125 150.0 120 118.0 184
3 111 128 194.0 114 150.0 168
4 187 187 194.0 196 122.0 113
5 109 107 163.0 161 122.0 157
6 101 100 160.0 181 108.0 188

五、创建多层索引

1、创建多层列索引

 1.隐式构造

最常见的方法是给DataFrame构造函数的index或者columns参数传递两个或更多的数组

# 1.示例
df = DataFrame(np.random.randint(100,150,size=(3,3)),index=['a','b','c'],columns=[['A','B','C'],['AA','BB','CC']])
    A B C
    AA BB CC
a 137 143 112
b 108 109 111
c 105 115 100

2. 显示构造pd.MultiIndex.from_product

pandas.MultiIndex.from_product(iterablessortorder = Nonenames = None)

从多个迭代的笛卡尔积中创建一个MultiIndex。

参数:
iterables : 列表/可迭代序列

每个iterable都为索引的每个级别都有唯一的标签。

sortorder : int或None

排序级别(必须按字典顺序按该级别排序)。

names : str的列表/序列,可选

索引中级别的名称。

返回:
index : MultiIndex
col=pd.MultiIndex.from_product([['qizhong','qimo'],
['chinese','math']]) df = DataFrame(data=np.random.randint(60,120,size=(2,4)),index=['tom','jay'],
columns=col) # 结果
qizhong qimo
   chinese math chinese math
tom 74   110   64 83
jay 83   101   109 115

2、创建多层行索引

# 跟创建列的一样
df = DataFrame(np.random.randint(100,150,size=(3,3)),index=[['a','b','c'],['aa','bb','cc']],columns=['A','B','C'])
   A B C
a aa 137 143 112
b bb 108 109 111
c cc 105 115 100 # MultiIndex.from_product
index=pd.MultiIndex.from_product([['all'],
['a','b']])
df = DataFrame(data=np.random.randint(60,120,size=(2,4)),index=index,
columns=['A','B','C','D'])

  A B C D
all a 76 61 72 67
b 105 66 85 110

3、多层索引对象的索引与切片操作

 1.索引操作

"""
注意在对行索引的时候,若一级行索引还有多个,对二级行索引会遇到问题!也就是说,无法直接对二级索引进行索引,必须让二级索引变成一级索引后才能对其进行索引!
DataFrame中直接用中括号[]时:
    索引表示的是列索引
    切片表示的是行切片
"""

# df
 qizhong qimo
   chinese math chinese math
tom 80 97 78 80
jay 71 102 88 89 # 1.获取所有学生所有科目期末考试成绩
df['qimo']
# 结果
chinese math
tom 78 80
jay 88 89 # 2.获取所有学生期末的math的考试成绩
df['qimo']['math']
# 结果
tom 80
jay 89
Name: math, dtype: int32 # 3.获取tom期中所有科目的考试成绩
df['qizhong'].loc['tom']
# 结果
chinese 80
math 97
Name: tom, dtype: int32 # 4.获取tom期末的math成绩
df['qimo'].loc['tom','math']
# 结果
80

2.切片操作

# 用切片的形式获取tom和jay期中的语文和数学成绩
df.loc['tom':'jay','qizhong']
# 结果
chinese math
tom 80   97
jay 71   102

3.总结

"""
总结:
直接使用[],索引是列索引,切片是行切片
1.索引
访问一列或多列 直接用中括号[columnname] [[columname1,columnname2...]]
访问一行或多行 .loc[indexname]
访问某一个元素 .loc[indexname,columnname] 获取李四期中的php成绩 2.切片:
行切片 .[index1:index2] 获取张三李四的期中成绩
列切片 .loc[:,column1:column2] 获取张三李四期中的php和c++成绩
"""

六、聚合操作

# df
qizhong qimo
   chinese math chinese math
tom 80   97 78 80
jay 71   102 88 89 # 1.每行最大的值
df.max(axis=1)
# 结果
tom 97
jay 102
dtype: int32 # 2.每列最小的值
df.min(axis=0)
# 结果
qizhong chinese 71
math 97
qimo chinese 78
math 80
dtype: int32 # 3.平均值mean()
df.mean(axis=1)
# 结果
tom 83.75
jay 87.50
dtype: float64 # 4.求和sum
df.sum(axis=1)
# 结果
tom 335
jay 350
dtype: int64 # 其他
Function Name NaN-safe Version Description
np.sum np.nansum Compute sum of elements
np.prod np.nanprod Compute product of elements
np.mean np.nanmean Compute mean of elements
np.std np.nanstd Compute standard deviation
np.var np.nanvar Compute variance
np.min np.nanmin Find minimum value
np.max np.nanmax Find maximum value
np.argmin np.nanargmin Find index of minimum value
np.argmax np.nanargmax Find index of maximum value
np.median np.nanmedian Compute median of elements
np.percentile np.nanpercentile Compute rank-based statistics of elements
np.any N/A Evaluate whether any elements are true
np.all N/A Evaluate whether all elements are true
np.power 幂运算

七、pandas的拼接操作

pandas的拼接分为两种:

  • 级联:pd.concat, pd.append
  • 合并:pd.merge, pd.join

1、使用pd.concat()级联

pandas使用pd.concat函数,与np.concatenate函数类似,只是多了一些参数:

objs
axis=0
keys
join='outer' / 'inner':表示的是级联的方式,outer会将所有的项进行级联(忽略匹配和不匹配),而inner只会将匹配的项级联到一起,不匹配的不级联
ignore_index 默认是False,如果设置为True,则代表 重建索引

 1.匹配级联

import pandas as pd
from pandas import Series,DataFrame
import numpy as np # 数据
df = DataFrame(np.random.randint(0,100,size=(3,3)),index=['a','b','c'],columns=['A','B','C'])
# 结果
    A B C
a 47 81 12
b 7 43 36
c 76 85 47 # outer级联匹配,行拼接
pd.concat([df,df],axis=1,join='outer')
# 结果
   A B C A B C
a 47 81 12 47 81 12
b 7 43 36 7 43 36
c 76 85 47 76 85 47

2.不匹配级联

不匹配指的是级联的维度的索引不一致。例如纵向级联时列索引不一致,横向级联时行索引不一致

有2种连接方式:

  • 外连接(outer):补NaN(默认模式)
  • 内连接(inner):只连接匹配的项
# 数据
# df
A B C
a 47 81 12
b 7 43 36
c 76 85 47 # df1
df1 = DataFrame(np.random.randint(0,100,size=(3,3)),index=['a','b','c'],columns=['A','B','D'])
   A B D
a 73 64 69
b 98 68 9
c 63 38 74 # inner只连接匹配项
pd.concat([df,df1],axis=0,join='inner',ignore_index=True)
# 结果
   A B
0 47 81
1 7 43
2 76 85
3 73 64
4 98 68
5 63 38 # outer全部都连接
pd.concat([df,df1],axis=0,join='outer')
# 结果
   A B C D
a 47 81 12.0 NaN
b 7 43 36.0 NaN
c 76 85 47.0 NaN
a 73 64 NaN 69.0
b 98 68 NaN 9.0
c 63 38 NaN 74.0

3.使用df.append()函数添加

由于在 纵轴下面 级联的使用非常普遍,因此有一个函数append专门用于在后面添加
df.append(df1)
   A B C D
a 47 81 12.0 NaN
b 7 43 36.0 NaN
c 76 85 47.0 NaN
a 73 64 NaN 69.0
b 98 68 NaN 9.0
c 63 38 NaN 74.0

2、使用pd.merge()合并

merge与concat的区别在于,merge需要依据某一共同的列来进行合并

使用pd.merge()合并时,会自动根据两者相同column名称的那一列,作为key来进行合并。

注意每一列元素的顺序不要求一致

参数:

  • how:outer取并集  inner取交集
  • on:当有多列相同的时候,可以使用on来指定使用那一列进行合并,on的值为一个列表

0.内合并与外合并:out取并集 inner取交集

内合并:how='inner'   只保留两者都有的key(默认模式)
外合并:how='outer' 补NaN

1. 一对一合并

# 数据
df1 = DataFrame({'employee':['Bob','Jake','Lisa'],
'group':['Accounting','Engineering','Engineering'],
})
# 结果
   employee group
0 Bob Accounting
1 Jake Engineering
2 Lisa Engineering df2 = DataFrame({'employee':['Lisa','Bob','Jake'],
'hire_date':[2004,2008,2012],
})
# 结果
   employee hire_date
0 Lisa    2004
1 Bob     2008
2 Jake    2012 # 合并,取交集
pd.merge(df1,df2,how='inner')
# 结果
  employee group hire_date
0 Bob Accounting 2008
1 Jake Engineering 2012
2 Lisa Engineering 2004

 2.多对一合并

# 数据
df3 = DataFrame({
'employee':['Lisa','Jake'],
'group':['Accounting','Engineering'],
'hire_date':[2004,2016]})
# 结果
employee group hire_date
0 Lisa Accounting 2004
1 Jake Engineering 2016 df4 = DataFrame({'group':['Accounting','Engineering','Engineering'],
'supervisor':['Carly','Guido','Steve']
})
# 结果
group supervisor
0 Accounting Carly
1 Engineering Guido
2 Engineering Steve # 多对一合并
pd.merge(df3,df4) # how默认是inner取交集
# 结果
employee group hire_date supervisor
0 Lisa Accounting 2004    Carly
1 Jake Engineering 2016    Guido
2 Jake Engineering 2016    Steve

 3.多对多合并

# 数据
df1 = DataFrame({'employee':['Bob','Jake','Lisa'],
'group':['Accounting','Engineering','Engineering']})
# 结果
employee group
0 Bob Accounting
1 Jake Engineering
2 Lisa Engineering df5 = DataFrame({'group':['Engineering','Engineering','HR'],
'supervisor':['Carly','Guido','Steve']
})
# 结果
     group supervisor
0 Engineering Carly
1 Engineering Guido
2 HR       Steve # 多对多outer取并集
pd.merge(df1,df5,how='outer')
# 结果
   employee group supervisor
0 Bob Accounting NaN
1 Jake Engineering Carly
2 Jake Engineering Guido
3 Lisa Engineering Carly
4 Lisa Engineering Guido
5 NaN HR      Steve

 4.额外知识点

  • 加载excl数据:pd.read_excel('excl_path',sheetname=1)
pd.read_excel('./data.xlsx',sheet_name=1)

 5.key的规范化

  • 当列冲突时,即有多个列名称相同时,需要使用on=来指定哪一个列作为key,配合suffixes指定冲突列名
# 数据
df1 = DataFrame({'employee':['Jack',"Summer","Steve"],
'group':['Accounting','Finance','Marketing']})
# 结果
   employee group
0 Jack Accounting
1 Summer Finance
2 Steve Marketing df2 = DataFrame({'employee':['Jack','Bob',"Jake"],
'hire_date':[2003,2009,2012],
'group':['Accounting','sell','ceo']})
# 结果
employee group hire_date
0 Jack Accounting 2003
1 Bob sell 2009
2 Jake ceo 2012 # on指定用哪个列合并
pd.merge(df1,df2,on='group',how='outer')
# 结果
employee_x group   employee_y hire_date
0 Jack Accounting Jack   2003.0
1 Summer Finance NaN NaN
2 Steve Marketing NaN    NaN
3 NaN sell    Bob    2009.0
4 NaN ceo    Jake 2012.0
  • 当两张表没有可进行连接的列时,可使用left_on和right_on手动指定merge中左右两边的哪一列列作为连接的列
# 数据
df1 = DataFrame({'employee':['Bobs','Linda','Bill'],
'group':['Accounting','Product','Marketing'],
'hire_date':[1998,2017,2018]})
# 结果
  employee group hire_date
0 Bobs Accounting 1998
1 Linda Product 2017
2 Bill Marketing 2018 df5 = DataFrame({'name':['Lisa','Bobs','Bill'],
'hire_dates':[1998,2016,2007]})
# 结果
  hire_dates name
0 1998    Lisa
1 2016    Bobs
2 2007    Bill # 左边指定用employee和右边的name作为key进行合并
pd.merge(df1,df5,left_on='employee',right_on='name',how='outer')
# 结果
employee group hire_date hire_dates name
0 Bobs Accounting 1998.0   2016.0 Bobs
1 Linda Product 2017.0    NaN    NaN
2 Bill Marketing 2018.0    2007.0 Bill
3 NaN   NaN     NaN    1998.0   Lisa

八、案例分析:美国各州人口数据分析

# 导入文件,查看原始数据
import numpy as np
from pandas import DataFrame,Series
import pandas as pd # 从csv文件中读取数据,文本在我本地
abb = pd.read_csv('./data/state-abbrevs.csv') # 洲
pop = pd.read_csv('./data/state-population.csv') # 人口
area = pd.read_csv('./data/state-areas.csv') # 面积 abb.head(1)
# 数据太多,这里只查看一条数据,为了查看行列名
state abbreviation
0 Alabama AL pop.head(1)
# 结果
state/region ages year population
0 AL     under18 2012 1117489.0 area.head(1)
# 结果
state area (sq. mi)
0 Alabama 52423 # 1.将人口数据和各州简称数据进行合并
abb_pop = pd.merge(abb,pop,how='outer',left_on='abbreviation',right_on='state/region')
abb_pop.head()
# 结果
   state abbreviation state/region ages year population
0 Alabama   AL       AL   under18 2012 1117489.0
1 Alabama   AL       AL   total 2012 4817528.0
2 Alabama   AL       AL    under18 2010 1130966.0
3 Alabama   AL       AL   total 2010 4785570.0
4 Alabama   AL       AL   under18 2011 1125763.0 # 2.将合并的数据中重复的abbreviation列进行删除
abb_pop.drop(labels='abbreviation',axis=1,inplace=True)
abb_pop.head()
# 结果
    state state/region ages year population
0 Alabama AL      under18 2012 1117489.0
1 Alabama AL      total 2012 4817528.0
2 Alabama AL       under18 2010 1130966.0
3 Alabama AL      total 2010 4785570.0
4 Alabama AL      under18 2011 1125763.0 # 3.查看存在缺失数据的列
abb_pop.isnull().any(axis=0)
# 结果
state True
state/region False
ages False
year False
population True
dtype: bool # 4.找到有哪些state/region使得state的值为NaN,进行去重操作
# state列中所有的空值
condition = abb_pop['state'].isnull()
# 找出state列空值对应的行数据
abb_pop.loc[condition]
# 去重:abb_pop.loc[condition]['state/region']得到的是Series
abb_pop.loc[condition]['state/region'].unique()
# 结果
array(['PR', 'USA'], dtype=object) # 5.为找到的这些state/region的state项补上正确的值,从而去除掉state这一列的所有NaN
# 获取原数据中所有USA对应的行索引
c = abb_pop['state/region'] == 'USA'
index = abb_pop.loc[c].index
abb_pop.loc[index,'state'] = 'United State' c1 = abb_pop['state/region'] == 'PR'
index1 = abb_pop.loc[c1].index
abb_pop.loc[index,'state'] = 'PPPRRR' # 6.合并各州面积数据areas
abb_pop_area = pd.merge(abb_pop,area,how='outer')
abb_pop_area.head(1)
# 结果
    state state/region ages  year population area (sq. mi)
0 Alabama AL      under18 2012.0 1117489.0 52423.0 # 7.我们会发现area(sq.mi)这一列有缺失数据,找出是哪些行
con = abb_pop_area['area (sq. mi)'].isnull()
index = abb_pop_area.loc[con].index # 8.去除含有缺失数据的行
abb_pop_area.drop(labels=index,axis=0,inplace=True) # 9.找出2010年的全民人口数据
abb_pop_area.query('year == 2010 & ages == "total"') # 10.计算各州的人口密度
abb_pop_area['midu'] = abb_pop_area['population'] / abb_pop_area['area (sq. mi)']
abb_pop_area.head()
# 结果
   state state/region ages year population area (sq. mi) midu
0 Alabama   AL   under18 2012.0 1117489.0 52423.0   21.316769
1 Alabama   AL   total 2012.0 4817528.0 52423.0    91.897221
2 Alabama   AL   under18 2010.0 1130966.0 52423.0    21.573851
3 Alabama   AL   total 2010.0 4785570.0 52423.0    91.287603
4 Alabama   AL   under18 2011.0 1125763.0 52423.0    21.474601 # 11.排序,并找出人口密度最高的五个州 df.sort_values()
abb_pop_area.sort_values(by='midu',axis=0,ascending=False).head()

九、pandas数据处理

1、删除重复行

使用duplicated()函数检测重复的行,返回元素为布尔类型的Series对象,每个元素对应一行,如果该行不是第一次出现,则元素为True

- keep参数:指定保留哪一重复的行数据
  • 使用duplicated(keep='first/last'/False)和drop函数删除重复行
# 1.创建具有重复元素行的DataFrame
np.random.seed(1)
df = DataFrame(data=np.random.randint(0,100,size=(8,6))) df.iloc[1] = [3,3,3,3,3,3]
df.iloc[3] = [3,3,3,3,3,3]
df.iloc[5] = [3,3,3,3,3,3]
# 结果
   0 1 2 3 4 5
0 37 12 72 9 75 5
1 3 3 3 3 3 3
2 6 25 50 20 18 84
3 3 3 3 3 3 3
4 87 87 94 96 86 13
5 3 3 3 3 3 3
6 1 0 60 81 8 88
7 13 47 72 30 71 3 # 2.使用duplicated查看所有重复元素行
keep参数:
keep=False:所有重复行都不保留
keep="last" 保留最后一行的重复行
keep="first" 保留第一行的重复行,默认值 # 这个数据的1,3,5行为重复行,设置keep="last"保留最后一行
con = df.duplicated(keep="last")
# 结果
0 False
1 True # 1行
2 False
3 True # 3行
4 False
5 False # 5行保留
6 False
7 False
dtype: bool # 3.删除重复元素的行
index = df.loc[con].index # 重复行的行索引
df.drop(labels=index,axis=0) # 删除
# 结果
 0 1 2 3 4 5
0 37 12 72 9 75 5
2 6 25 50 20 18 84
4 87 87 94 96 86 13
5 3 3 3 3 3 3
6 1 0 60 81 8 88
7 13 47 72 30 71 3
  • 使用drop_duplicates(keep='first/last'/False)函数删除重复行
"""
drop_duplicates()相当于上面的duplicated和drop函数的结合
"""
# 保留最开始的重复行,其他删除
df.drop_duplicates(keep='first')
# 结果
 0 1 2 3 4 5
0 37 12 72 9 75 5
1 3  3 3 3 3 3
2 6 25 50 20 18 84
4 87 87 94 96 86 13
6 1 0 60 81 8 88
7 13 47 72 30 71 3

2、映射

replace()函数:替换元素

使用replace()函数,对values进行映射操作

1.Series替换操作

  • 单值替换

    • 普通替换
    • 字典替换(推荐)
  • 多值替换
    • 列表替换
    • 字典替换(推荐)
  • 参数
    • to_replace:被替换的元素
# 1.单值普通替换
s = Series([1,2,3,4,5,6]) s.replace(to_replace=3,value='three')
# 结果
0 1
1 2
2 three
3 4
4 5
5 6
dtype: object # 2.单值字典替换
s.replace(to_replace={1:'one'})
# 结果
0 one
1 2
2 3
3 4
4 5
5 6
dtype: object # 3.多值列表替换
s.replace(to_replace=[1,2],value=['a','b'])
# 结果
0 a
1 b
2 3
3 4
4 5
5 6
dtype: object # 4.多值字典替换
s.replace(to_replace={3:"three",4:"four"})
# 结果
0 1
1 2
2 three
3 four
4 5
5 6
dtype: object # 5.method参数
method:对指定的值使用相邻的值填充替换,{'pad','ffill','bfill',None}
limit:设定填充次数, int,默认None # 用前面的值替换
s.replace(to_replace=3,method='ffill')
# 结果
0 1
1 2
2 2 # 3被前面的2替换了
3 4
4 5
5 6
dtype: int64 # 用后面的值替换
s.replace(to_replace=3,method='bfill')
# 结果
0 1
1 2
2 4 # 3被后面的4替换了
3 4
4 5
5 6
dtype: int64

 2.DataFrame替换操作

  • 单值替换

    • 普通替换: 替换所有符合要求的元素:to_replace=15,value='e'
    • 按列指定单值替换: to_replace={列标签:要被替换的元素},value='value'
  • 多值替换

    • 列表替换: to_replace=[] value=[]
    • 字典替换(推荐) to_replace={列标签1:要被替换的元素1,列标签2:要被替换的元素2},value='value'
# df
   0 1 2 3 4 5
0 37 12 72 9 75 5
1 3 3 3 3 3 3
2 6 25 50 20 18 84
3 3 3 3 3 3 3
4 87 87 94 96 86 13
5 3 3 3 3 3 3
6 1 0 60 81 8 88
7 13 47 72 30 71 3 # 1.单值替换
df.replace(to_replace=3,value='three') # 把所有 3 元素替换成three
# 结果
   0   1    2    3    4    5
0 37   12    72    9    75   5
1 three three three three three three
2 6    25   50   20   18   84
3 three three three three three three
4 87   87   94   96  86   13
5 three three three three three three
6 1    0    60   81 8 88
7 13   47   72   30   71 three # 2.多值列表替换
df.replace(to_replace=[1,3],value=['one','three'])
# 结果
   0 1   2   3   4    5
0 37 12   72   9   75 5
1 three three three three three three
2 6   25 50 20 18 84
3 three three three three three three
4 87 87   94   96   86   13
5 three three three three three three
6 one 0 60   81    8    88
7 13   47   72   30    71 three # 3.字典替换
# 把第3列的 3 元素替换成'aaaa'
df.replace(to_replace={3:3},value='aaaa')
# 结果
   0 1 2 3 4 5
0 37 12 72 9 75 5
1 3 3 3 aaaa 3 3
2 6 25 50 20 18 84
3 3 3 3 aaaa 3 3
4 87 87 94 96 86 13
5 3 3 3 aaaa 3 3
6 1 0 60 81 8 88
7 13 47 72 30 71 3 # 4.把第3列的3和第4列的3替换成three
df.replace(to_replace={3:3,4:3},value='three')
# 结果    0 1 2 3 4 5
0 37 12 72 9 75 5
1 3 3 3 three three 3
2 6 25 50 20 18 84
3 3 3 3 three three 3
4 87 87 94 96 86 13
5 3 3 3 three three 3
6 1 0 60 81 8 88
7 13 47 72 30 71 3 注意:DataFrame中,无法使用method和limit参数

3.map()函数:新建一列 , map函数并不是df的方法,而是series的方法

  • map()可以映射新一列数据
  • map()中可以使用lambda表达式
  • map()中可以使用方法,可以是自定义的方法

    eg:map({to_replace:value})

  • 注意 map()中不能使用sum之类的函数,for循环
"""
注意:并不是任何形式的函数都可以作为map的参数。只有当一个函数具有一个参数且有返回值,那么该函数才可以作为map的参数
""" # 1.新增一列:给df中,添加一列,该列的值为英文名对应的中文名
dic = {
'name':['jay','tom','jay'],
'salary':[10000,8000,2000]
}
df = DataFrame(data=dic)
# 结果
   name salary
0 jay 10000
1 tom 8000
2 jay 2000 # 映射关系表
dic = {
'jay':'周杰伦',
'tom':'张三'
}
df['c_name'] = df['name'].map(dic) # 把name这一列的数据替换成dic的内容,并新增到新的c_name列中
# 结果
   name salary c_name
0 jay 10000 周杰伦
1 tom 8000 张三
2 jay 2000 周杰伦 map当做一种运算工具,至于执行何种运算,是由map函数的参数决定的(参数:lambda,函数) # 2.使用自定义函数
# 函数
def after_sal(s):
if s <= 3000:
return s
else:
return s - (s-3000)*0.5 # 超过3000部分的钱缴纳50%的税
df['salary'].map(after_sal)
# 结果
0 6500.0
1 5500.0
2 2000.0
Name: salary, dtype: float64 # 新增列到原数据中
df['after_sal'] = df['salary'].map(after_sal)
# 结果
name salary c_name after_sal
0 jay 10000 周杰伦 6500.0
1 tom 8000 张三 5500.0
2 jay 2000 周杰伦   2000.0 # 3.使用lambda函数
# 给每个人工资加1000块
df['sal_1000'] = df['salary'].map(lambda x:x+1000)
# 结果
   name salary c_name after_sal sal_1000
0 jay 10000 周杰伦 6500.0 11000
1 tom 8000 张三 5500.0 9000
2 jay 2000 周杰伦 2000.0 3000

3、使用聚合操作对数据异常值检测和过滤

使用df.std()函数可以求得DataFrame对象每一列的标准差

# 1.创建一个1000行3列的df 范围(0-1),求其每一列的标准差
df = DataFrame(np.random.random(size=(1000,3)),columns=['A','B','C'])
df.head()
# 部分结果
      A     B     C
0 0.671654 0.411788 0.197551
1 0.289630 0.142120 0.783314
2 0.412539 0.034171 0.624030
3 0.660636 0.298495 0.446135
4 0.222125 0.073364 0.469239 # 2.对df应用筛选条件,去除标准差太大的数据:假设过滤条件为 C列数据大于两倍的C列标准差
# 两倍的C列标准差
value = df['C'].std() * 2 # 结果
df.loc[df['C'] > value]

4.、排序

使用.take()函数排序

- take()函数接受一个索引列表,用数字表示,使得df根据列表中索引的顺序进行排序
- eg:df.take([1,3,4,2,5])
# 1.数据
df = DataFrame(data=np.random.randint(0,100,size=(8,4)),columns=['A','B','C','D'])
# 结果
A B C D
0 77 72 75 76
1 43 20 30 36
2 7 45 68 57
3 82 96 13 10
4 23 81 7 24
5 74 92 20 32
6 12 65 94 60
7 24 82 97 2 # 2.排序列
df.take([1,2,0,3],axis=1)
# 结果
   B C A D
0 72 75 77 76
1 20 30 43 36
2 45 68 7 57
3 96 13 82 10
4 81 7 23 24
5 92 20 74 32
6 65 94 12 60
7 82 97 24 2 # 3.排序行
df.take([7,3,4,1,5,2,0]) # axis默认等于0,为行排序,且没排序的不显示
# 结果(第6行没有排序,所有没有显示出来)
   A B C D
7 24 82 97 2
3 82 96 13 10
4 23 81 7 24
1 43 20 30 36
5 74 92 20 32
2 7 45 68 57
0 77 72 75 76

可以借助np.random.permutation()函数随机排序实现随机抽样

  • np.random.permutation(x)可以生成x个从0-(x-1)的随机数列
  • 当DataFrame规模足够大时,直接使用np.random.permutation(x)函数,就配合take()函数实现随机抽样
"""
如果有1000行,用take,参数列表不是要写1000个元素吗,
因此不科学,可以借助np.random.permutation()函数随机进行排序 示例
np.random.permutation(7)
生成0到6的随机数列
结果每次都是不同的:array([0, 3, 4, 2, 1, 5, 6])
""" # 把行和列都打乱顺序
new_df = df.take(np.random.permutation(7),axis=0).take(np.random.permutation(3),axis=1)
# 结果
C A B
2 68 7 45
6 94 12 65
4 7 23 81
5 20 74 92
3 13 82 96
1 30 43 20
0 75 77 72 # 在打乱了顺序的数据中获取一部分数据
new_df2 = new_df[2:6] # 这里数据较少,实际中的随机抽样数据肯定很多的,这里只是演示 # 生成新的数据,即是随机抽样的数据
new_df3 = DataFrame(data=new_df2.values)

5、数据分类处理(重)

数据聚合是数据处理的最后一步,通常是要使每一个数组生成一个单一的数值。

数据分类处理:

  • 分组:先把数据分为几组
  • 用函数处理:为不同组的数据应用不同的函数以转换数据
  • 合并:把不同组得到的结果合并起来

数据分类处理的核心:

 - groupby()函数
- groups属性查看分组情况
- eg: df.groupby(by='item').groups

 1.分组聚合

# 1.数据
df = DataFrame({'item':['Apple','Banana','Orange','Banana','Orange','Apple'],
'price':[4,3,3,2.5,4,2],
'color':['red','yellow','yellow','green','green','green'],
'weight':[12,20,50,30,20,44]})
# 结果
   color item price weight
0 red Apple 4.0 12
1 yellow Banana 3.0 20
2 yellow Orange 3.0 50
3 green Banana 2.5 30
4 green Orange 4.0 20
5 green Apple 2.0 44 # 2.使用groupby实现分组
df.groupby(by='item') # <pandas.core.groupby.DataFrameGroupBy object at 0x00000152DB865DA0> # 3.使用groups查看分组情况
# 该函数可以进行数据的分组,但是不显示分组情况
df.groupby(by='item').groups
# 结果
{'Apple': Int64Index([0, 5], dtype='int64'),
'Banana': Int64Index([1, 3], dtype='int64'),
'Orange': Int64Index([2, 4], dtype='int64')} # 4.分组后的聚合操作:分组后的成员中可以被进行运算的值会进行运算,不能被运算的值不进行运算
# 各种水果的平均价格和平均重量
df.groupby(by='item').mean()
# 结果
   item price weight
Apple 3.00    28
Banana 2.75     25
Orange 3.50    35 # 创建新的一列为水果的平均价格
mean_price = df.groupby(by='item')['price'].mean() # 平均价格
# 结果
item
Apple 3.00
Banana 2.75
Orange 3.50
Name:price, dtype:float64
# 构建字典
dic = {
'Apple':3,
'Banana':2.75,
'Orange':3.5
}
# 映射
df['mean_price'] = df['item'].map(dic)
# 结果
   color item price weight mean_price
0 red Apple 4.0  12   3.00
1 yellow Banana 3.0  20   2.75
2 yellow Orange 3.0  50   3.50
3 green Banana 2.5  30   2.75
4 green Orange 4.0  20   3.50
5 green Apple 2.0  44   3.00 # 5.按颜色查看各种颜色的水果的平均价格,并新建一列
s = df.groupby(by='color')['price'].mean()
# 结果
color
green 2.833333
red 4.000000
yellow 3.000000
Name:price, dtype:float64 # 可以使用to_dict()构建字典
df['color_mean_price'] = df['color'].map(s.to_dict())
# 结果
   color item price weight mean_price color_mean_price
0 red Apple 4.0   12    3.00     4.000000
1 yellow Banana 3.0   20   2.75      3.000000
2 yellow Orange 3.0   50   3.50      3.000000
3 green Banana 2.5   30   2.75      2.833333
4 green Orange 4.0   20   3.50      2.833333
5 green Apple 2.0   44   3.00      2.833333

6、高级数据聚合

使用groupby分组后,也可以使用transform和apply提供自定义函数实现更多的运算

  • df.groupby('item')['price'].sum() <==> df.groupby('item')['price'].apply(sum)
  • transform和apply都会进行运算,在transform或者apply中传入函数即可
  • transform和apply也可以传入一个lambda表达式
# 1.求出各种水果价格的平均值
df.groupby(by='item')['price'].mean() # 2.使用apply函数求出各种水果价格的平均值
def fun(s):
sum = 0
for i in s:
sum += s
return s/s.size df.groupby(by='item')['price'].apply(fun) # 3.使用transform函数求出水果的平均价格
df.groupby(by='item')['price'].transform(fun)

十、案例分析:美国2012年总统候选人政治献金数据分析

# 1.导包
import numpy as np
import pandas as pd
from pandas import Series,DataFrame # 2.方便大家操作,将月份和参选人以及所在政党进行定义
months = {'JAN' : 1, 'FEB' : 2, 'MAR' : 3, 'APR' : 4, 'MAY' : 5, 'JUN' : 6,
'JUL' : 7, 'AUG' : 8, 'SEP' : 9, 'OCT': 10, 'NOV': 11, 'DEC' : 12}
of_interest = ['Obama, Barack', 'Romney, Mitt', 'Santorum, Rick',
'Paul, Ron', 'Gingrich, Newt']
parties = {
'Bachmann, Michelle': 'Republican',
'Romney, Mitt': 'Republican',
'Obama, Barack': 'Democrat',
"Roemer, Charles E. 'Buddy' III": 'Reform',
'Pawlenty, Timothy': 'Republican',
'Johnson, Gary Earl': 'Libertarian',
'Paul, Ron': 'Republican',
'Santorum, Rick': 'Republican',
'Cain, Herman': 'Republican',
'Gingrich, Newt': 'Republican',
'McCotter, Thaddeus G': 'Republican',
'Huntsman, Jon': 'Republican',
'Perry, Rick': 'Republican'
} # 3.读取文件
data = pd.read_csv('./data/usa_election.txt') # 4.使用map函数+字典,新建一列各个候选人所在党派party
data['party'] = data['cand_nm'].map(parties)
# 5.使用np.unique()函数查看colums:party这一列中有哪些元素
data['party'].unique()
# 结果
array(['Republican', 'Democrat', 'Reform', 'Libertarian'], dtype=object) # 6.使用value_counts()函数,统计party列中各个元素出现次数
data['party'].value_counts()
# 结果
Democrat 292400
Republican 237575
Reform 5364
Libertarian 702
Name: party, dtype: int64 # 7.使用groupby()函数,查看各个党派收到的政治献金总数contb_receipt_amt
data.groupby(by='party')['contb_receipt_amt'].sum()
# 结果
party
Democrat 8.105758e+07
Libertarian 4.132769e+05
Reform 3.390338e+05
Republican 1.192255e+08
Name: contb_receipt_amt, dtype: float64 # 8.查看具体每天各个党派收到的政治献金总数contb_receipt_amt
使用groupby([多个分组参数])
data.groupby(by=['party','contb_receipt_dt'])['contb_receipt_amt'].sum() # 9.查看日期格式,并将其转换为'yyyy-mm-dd'日期格式,通过函数加map方式进行转换:months['月份简写']==》mm形式的月份
def tranform_date(d): # 20-JUN-11
day,month,year = d.split('-')
month = str(months[month]) return ''+year+'-'+month+'-'+day data['contb_receipt_dt'] = data['contb_receipt_dt'].map(tranform_date)
# 10.查看老兵(捐献者职业)DISABLED VETERAN主要支持谁 :查看老兵们捐赠给谁的钱最多 考察Series索引
# 获取老兵对应的行数据
data['contbr_occupation'] == 'DISABLED VETERAN' old_bing = data.loc[data['contbr_occupation'] == 'DISABLED VETERAN'] old_bing.groupby(by='cand_nm')['contb_receipt_amt'].sum()
# 结果
cand_nm
Cain, Herman 300.00
Obama, Barack 4205.00
Paul, Ron 2425.49
Santorum, Rick 250.00
Name: contb_receipt_amt, dtype: float64 # 11.找出候选人的捐赠者中,捐赠金额最大的人的职业以及捐献额
# 通过query("查询条件来查找捐献人职业")
data['contb_receipt_amt'].max() # 1944042.43
data.query('contb_receipt_amt == 1944042.43')

数据分析之Pandas的更多相关文章

  1. 利用Python进行数据分析(12) pandas基础: 数据合并

    pandas 提供了三种主要方法可以对数据进行合并: pandas.merge()方法:数据库风格的合并: pandas.concat()方法:轴向连接,即沿着一条轴将多个对象堆叠到一起: 实例方法c ...

  2. 利用Python进行数据分析(9) pandas基础: 汇总统计和计算

    pandas 对象拥有一些常用的数学和统计方法.   例如,sum() 方法,进行列小计:   sum() 方法传入 axis=1 指定为横向汇总,即行小计:   idxmax() 获取最大值对应的索 ...

  3. 利用Python进行数据分析(8) pandas基础: Series和DataFrame的基本操作

    一.reindex() 方法:重新索引 针对 Series   重新索引指的是根据index参数重新进行排序. 如果传入的索引值在数据里不存在,则不会报错,而是添加缺失值的新行. 不想用缺失值,可以用 ...

  4. 利用Python进行数据分析(7) pandas基础: Series和DataFrame的简单介绍

    一.pandas 是什么 pandas 是基于 NumPy 的一个 Python 数据分析包,主要目的是为了数据分析.它提供了大量高级的数据结构和对数据处理的方法. pandas 有两个主要的数据结构 ...

  5. Python数据分析库pandas基本操作

    Python数据分析库pandas基本操作2017年02月20日 17:09:06 birdlove1987 阅读数:22631 标签: python 数据分析 pandas 更多 个人分类: Pyt ...

  6. Python数据分析之pandas基本数据结构:Series、DataFrame

    1引言 本文总结Pandas中两种常用的数据类型: (1)Series是一种一维的带标签数组对象. (2)DataFrame,二维,Series容器 2 Series数组 2.1 Series数组构成 ...

  7. Python 数据分析:Pandas 缺省值的判断

    Python 数据分析:Pandas 缺省值的判断 背景 我们从数据库中取出数据存入 Pandas None 转换成 NaN 或 NaT.但是,我们将 Pandas 数据写入数据库时又需要转换成 No ...

  8. 数据分析06 /pandas高级操作相关案例:人口案例分析、2012美国大选献金项目数据分析

    数据分析06 /pandas高级操作相关案例:人口案例分析.2012美国大选献金项目数据分析 目录 数据分析06 /pandas高级操作相关案例:人口案例分析.2012美国大选献金项目数据分析 1. ...

  9. 数据分析05 /pandas的高级操作

    数据分析05 /pandas的高级操作 目录 数据分析05 /pandas的高级操作 1. 替换操作 2. 映射操作 3. 运算工具 4. 映射索引 / 更改之前索引 5. 排序实现的随机抽样/打乱表 ...

  10. 数据分析02 /pandas基础

    数据分析02 /pandas基础 目录 数据分析02 /pandas基础 1. pandas简介 2. Series 3. DataFrame 4. 总结: 1. pandas简介 numpy能够帮助 ...

随机推荐

  1. 浅析 JavaScript 中的 函数 uncurrying 反柯里化

    柯里化 柯里化又称部分求值,其含义是给函数分步传递参数,每次传递参数后部分应用参数,并返回一个更具体的函数接受剩下的参数,这中间可嵌套多层这样的接受部分参数函数,直至返回最后结果. 因此柯里化的过程是 ...

  2. WEB前端常见面试题汇总:(一)

    1.JS找字符串中出现最多的字符 例如:求字符串'nininihaoa'中出现次数最多字符 方法一: var str = "nininihaoa"; var o = {}; for ...

  3. Dynamics CRM教程:图表的Top设置及导出修改和导入

    关注本人微信和易信公众号: 微软动态CRM专家罗勇,回复144或者20150412可方便获取本文,同时可以在第一时间得到我发布的最新的博文信息,follow me! 上一篇博客制作的图表放在Dashb ...

  4. 2019Java查漏补缺(二)

    查看了公众号:java之间的整理的集和文章,文章地址 总结和搜索了一下网络知识,总结了一下: 1.String 的hashcode()方法 2.switch总结: 3.如何实现克隆 1.String ...

  5. Ubuntu 18.04 安装博通(Broadcom)无线网卡驱动

    目录 Ubuntu 18.04 安装博通(Broadcom)无线网卡驱动 Package gcc is not configured yet. 解决办法 history history | grep ...

  6. java使用synchronized与Semaphore解决生产者消费者问题对比

    一.synchronized与信号量Semaphore简介 1.synchronized是java中的关键字,是用来控制线程同步的问题最常用的方法. 2.Semaphore是属于java的一个类,同样 ...

  7. c/c++ 多线程 等待一次性事件 std::promise用法

    多线程 等待一次性事件 std::promise用法 背景:不是很明白,不知道为了解决什么业务场景,感觉std::async可以优雅的搞定一切的一次等待性事件,为什么还有个std::promise. ...

  8. Linux 自动化部署DNS服务器

    Linux 自动化部署DNS服务器 1.首先配置主DNS服务器的IP地址,DNS地址一个写主dns的IP地址,一个写从dns的地址,这里也可以不写,在测试的时候在/etc/resolv.conf中添加 ...

  9. SQLServer之修改UNIQUE约束

    使用SSMS数据库管理工具修改UNIQUE约束 1.连接数据库,选择数据表->右键点击->选择设计(或者展开键,选择要修改的键,右键点击,选择修改,后面步骤相同). 2.选择要修改的数据列 ...

  10. About Pull Strings 英语走后门议论文

    About pull strings Author : Pleiades_Antares 1. From ancient times to the present, the "going b ...