pandas的基本使用

pandas的基本使用

  • pandas三剑客
# 财务部门
import numpy as np
# 业务部门
import pandas as pd
# UI部门
import matplotlib.pyplot as plt
# 导入两种数据类型
from pandas import Series, DataFrame

Series数组

  • 一维数组:一组【有序的】,【数据类型相同】的集合
  • Series是一种【类似】于【一维数组】的对象,由下面两个部分组成:
    • values:一组数据(ndarray类型)
    • index:相关的数据索引标签

Series的创建

  • 格式
    Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
    两种创建方式:
  • 由列表或numpy数组创建
    默认索引为0到N-1的整数型索引
#列表创建
l1 = [1,2,3,4,5]
#如果没有设置索引,会自动以隐式索引替代
s1 = Series(l1)	==>
0    1
1    2
2    3
3    4
4    5
dtype: int64

#ndarray创建
arr2 = np.random.randint(0,10,size=4)
s3 = Series(arr2)	==>
0    0
1    3
2    1
3    3
dtype: int32


#列表作为索引(副本),array作为值创建(引用)
#由ndarray创建的是引用,而不是副本。对Series元素的改变也会改变原来的ndarray对象中的元素。(列表没有这种情况)
data = np.random.randint(0,100,size=3)
index = ["python","java","php"]
s = Series(data=data, index=index)
s	==>
python    18
java      94
php       39
dtype: int32
  • 由字典创建
name_dic = {
    "tom":19,
    "mery":20,
    "lucy":19,
    "jery":21
}
#默认使用字典的键
Series(data=name_dic) ==>
jery    21
lucy    19
mery    20
tom     19
dtype: int64

#使用定义的键
Series(data=name_dic,index=["tom","mery"])	==>
tom     19
mery    20
dtype: int64

Series的索引和切片

  • 索引
    可以使用中括号取单个索引(此时返回的是元素类型),或者中括号里一个列表取多个索引(此时返回的仍然是一个Series类型)。分为显示索引和隐式索引:

    (1) 显式索引:

    • 使用index中的元素作为索引值
    • 使用.loc[](推荐)
      注意,此时是闭区间

    (2) 隐式索引:

    • 使用整数作为索引值
    • 使用.iloc[](推荐)
      注意,此时是半开区间
dic = {
    "name":"tom",
    "address":"beijing",
    "score":100
}
# 【注意】sereis对象也会强制统一数据类型
s1 = Series(data=dic) ==>
address    beijing
name           tom
score          100
dtype: object

#显示访问
# 字典的方式访问
s1["name"]	==>'tom'
# Series特有的访问形式
# 为的是统一访问形式
s1.loc["name"]	==>'tom'

#隐式访问
s1[1] ==>'tom'
s1.iloc[1] ==>'tom'

# 【重点】
# loc[key]
# iloc[index]
  • 切片
    • 但凡是隐式索引访问的,都是左闭右开
    • 但凡是显示索引访问的,都是左闭右闭区间
#显示索引切片
s1.loc["address":"name"] ==>
address    beijing
name           tom
dtype: object

#隐式索引切片
# 使用隐式索引切片
s1.iloc[0:2]	==>
address    beijing
name           tom
dtype: object

Series的属性和方法

  • 属性
    可以把Series看成一个定长的有序字典,可以通过shape,size,index,values,name,dtype等得到series的属性
s ==>
语文    150
数学    130
英语    140
理综    300
dtype: int64
#shape属性
s.shape ==> (4,)
#size属性
s.size ==>4
#index属性
s.index ==>
Index(['语文', '数学', '英语', '理综'], dtype='object')
#values属性
s.values ==>
array([150, 130, 140, 300], dtype=int64)
#name属性(得到列索引值)
#dtype属性
s.dtype ==>dtype('int64')

## 拓展:如何研究一个陌生的类型??
type(s.index) ==>pandas.core.indexes.base.Index
from pandas.core.indexes.base import Index
使用help(Index)或者Index?? 来查帮助文档
pd.Index(["A","B","C"])	==>
Index(['A', 'B', 'C'], dtype='object')

  • 方法
    • 常用的:
      • value_counts
      • sort_values
      • sort_index
      • isnull().any()
      • s[s.isnull()]
      • s[s.notnull()]
      • s.head()
      • s.tail()
#value_counts 统计Series中,每一个值出现的次数,一般统计的是离散值
data = ["tom","jack","tom","tom","jack","lucy","tom","jack"]
s = Series(data)	==>
0     tom
1    jack
2     tom
3     tom
4    jack
5    lucy
6     tom
7    jack
dtype: object

#value_counts
s.value_counts() ==>
tom     4
jack    3
lucy    1
dtype: int64

#unique()去重函数,查看一个Series中存在哪些值
s.unique() ==>
array(['tom', 'jack', 'lucy'], dtype=object)

#可以使用head(),tail()分别查看前n个和后n个值
s.head(2)	==>
0     tom
1    jack
dtype: object
s.tail(2) ==>
6     tom
7    jack
dtype: object

#对值和索引排序
s  ==>
0    88
1    27
2    96
3    24
4    47
5     1
6    36
7    63
8     1
9    34
dtype: int32
#值排序
s1 = s.sort_values()	==>
5     1
8     1
3    24
1    27
9    34
6    36
4    47
7    63
0    88
2    96
dtype: int32
#索引排序(索引需要是数字类型)
s1.sort_index() ==>
0    88
1    27
2    96
3    24
4    47
5     1
6    36
7    63
8     1
9    34
dtype: int32

  • 使用Bool_list访问数组对象
    BOOL型的列表可以读取列表数据,True对应的值就会返回,False对应的值就放弃
s1 ==>
0    2.0
1    1.0
2    NaN
3    4.0
4    NaN
dtype: float64
#普通版
bool_list = [True, False,True, False, False]
s1[bool_list]	==>
0    2.0
2    NaN
dtype: float64


# 获取空值的数据
s1.loc[s1.isnull()]  ==>
2   NaN
4   NaN
dtype: float64

# 过滤掉空值
s1.loc[s1.notnull()]
0    2.0
1    1.0
3    4.0
dtype: float64

Series的运算

  • 适用于numpy的数组运算也适用于Series
# 和一个数运算
s = Series(data=np.array([1,2,3,4,5]))
s + 8		==>
0     9
1    10
2    11
3    12
4    13
dtype: int32
  • Series之间的运算
    • 在运算中自动对齐不同索引的数据

    • 如果索引不对应,则补NaN

    • pandas的空值和任何数运算,都得到np.nan

       np.nan + 10000 ==> nan
      
s1 = Series(data=np.array([1,2,3,4,5]), index=list("ABCDE"))
s2 = Series(data=np.array([10,20,30,40,50]), index=list("BCDEF"))
s1 + s2 	==>
A     NaN
B    12.0
C    23.0
D    34.0
E    45.0
F     NaN
dtype: float64

#注意:要想保留所有的index,则需要使用
add() 加
sub() 减
mul() 乘
div() 除
s1.add(s2, fill_value=0)	 ==>
A     1.0
B    12.0
C    23.0
D    34.0
E    45.0
F    50.0
dtype: float64

DataFrame

  • 概念
    DataFrame是一个【表格型】的数据结构,可以看做是【由Series组成的字典】(共用同一个索引)。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。
    • 行索引:index
    • 列索引:columns
    • 值:values(numpy的二维数组)

DataFrame的创建

最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。
此外,DataFrame会自动加上每一行的索引(和Series一样)。
同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。

# 1、字典创建
dic1 = {
    "name":["jack","lucy","tom"],
    "python":[100,98,99],
    "java":[98,79,86],
    "C":[68,98,87]
}
df1 = DataFrame(data=dic1)	==>

	C  java name	python
0	68	98	jack	100
1	98	79	lucy	98
2	87	86	tom	    99


# 2、列表数组创建
data = np.random.randint(0,100,size=(3,4))
index = list("ABC")
columns = list("abcd")
df2 = DataFrame(data=data, index=index, columns=columns)	==>
	a	b	c	d
A	87	33	63	71
B	79	62	7	28
C	58	74	11	49

# 3、读取外部excel表格 
 pd.read_excel(io, sheetname=0, header=0, skiprows=None, skip_footer=0, index_col=None, names=None, parse_cols=None, parse_dates=False, date_parser=None, na_values=None, thousands=None, convert_float=True, has_index_names=None, converters=None, dtype=None, true_values=None, false_values=None, engine=None, squeeze=False, **kwds)
df3 = pd.read_excel('data.xlsx', sheet_name=1)


#4、直接把一个Series转换成DataFrame
s = Series(data=np.random.randint(0,10,size=(5)), index=list("ABCDE"), name="python")
DataFrame(s)  ==>
	python
A	3
B	1
C	1
D	7
E	4

DataFrame的属性

DataFrame属性:values、columns、index、shape、dtypes

dic = {
    "zhangsan":[150,150,150,300],
    "lisi":[10,20,70,88]
}
df = DataFrame(data=dic, index=["chinese","math","english","lizong"])			==>
	lisi	zhangsan
chinese	10	150
math	20	150
english	70	150
lizong	88	300

#df.dtypes
df.dtypes  ==>
lisi        int64
zhangsan    int64
dtype: object

df.shape  ==>(4, 2)

df.index		==>Index(['chinese', 'math', 'english', 'lizong'], dtype='object')

df.columns  	==>Index(['lisi', 'zhangsan'], dtype='object')

df.size	==>	8


#拓展
分布直方图
df.plot(kind="bar")

在这里插入图片描述

DataFrame的索引

  • 对列进行索引
    • 通过类似字典的方式
    • 通过属性的方式
      可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。
#创建
columns = ["python","java","name","address"]
data = np.random.randint(0,100,size=(5,4))
df = DataFrame(data=data, columns=columns)	==>
	python	java	name	address
0	28	26	93	60
1	40	45	96	26
2	69	18	71	64
3	45	46	55	0
4	85	23	51	95

#字典式访问
# 把DataFrame看成一个字典,每一个列标签,就是字典的键,对应的值就是这一列数据
df["address"]

#赋值
df["address"] = ["北京","上海","广州","深圳","武汉"]
df   ==>
	python	java	name	address
0	22	70	36	北京
1	64	4	94	上海
2	89	36	46	广州
3	62	98	17	深圳
4	69	75	4	武汉

#使用属性访问
df.address

# 访问多列数据
df[["address","name"]]

  • 对行进行索引
    • 使用.ix[]来进行行索引
    • 使用.loc[]加index来进行行索引
    • 使用.iloc[]加整数来进行行索引
      同样返回一个Series,series的index为datafrom的columns。
df    ==>
python	java	name	address
0	28	26	93	北京
1	40	45	96	上海
2	69	18	71	广州
3	45	46	55	深圳
4	85	23	51	武汉
#访问
df.loc[0]		==>
python     28
java       26
name       93
address    北京
Name: 0, dtype: object

#改变行索引
df.index = list("abcde")	==>

python	java	name	address
a	28	26	93	北京
b	40	45	96	上海
c	69	18	71	广州
d	45	46	55	深圳
e	85	23	51	武汉

#多行访问
df.loc[["a","b"]]

#隐式访问
df.iloc[0]	==>
python     28
java       26
name       93
address    北京
Name: a, dtype: object
df.iloc[1]
  • 对元素索引的方法
    • 使用列索引 .loc[index,columns]
    • 使用行索引(iloc[3,1]相当于两个参数;iloc[[3,3]] 里面的[3,3]看做一个参数)
    • 使用values属性(二维numpy数组)
df		==>
	python	java	name	address
a	28	26	93	北京
b	40	45	96	上海
c	69	18	71	广州
d	45	46	55	深圳
e	85	23	51	武汉

#显式访问
df.loc["b","java"]	==>45
# 隐式访问
df.iloc[1,1]		==>45
# 使用DataFrame的values属性访问
df.values[1,1]		==>45

总结:

	 列访问  df[column]
	行访问  df.loc[index]
	元素访问  df.loc[index, column] 

切片

  • 【注意】 直接用中括号时:
    • 索引表示的是列索引
    • 切片表示的是行切片
  • 行切片 df[index1:index2]
  • 列切片 df.loc[:, column1:column2]
  • 块切片 df.loc[index1:index2, column1:column2]
  • 其他写法:间接获取,可能是个引用,也可能是一个副本
    • read是没有问题的, write有可能有问题,因为很可能你操作的是一个副本对象
df   ==>
	python	java	name	address
a	22	70	36	北京
b	64	4	94	上海
c	89	36	46	广州
d	62	98	17	深圳
e	69	75	4	武汉

#行切片
df["a":"b"]				==>
	python	java	name	address
a	28	26	93	北京
b	40	45	96	上海

#列切片
df.loc[:,"python":"java"]	==>
	python	java
a	28	26
b	40	45
c	69	18
d	45	46
e	85	23

#快切片
df.loc["c":"d","name":"address"]		==>
name	address
c	71	广州
d	55	深圳

#间接访问
df1 = df.loc[["b","c"]]
df1["address"]		==>
b    上海
c    广州
Name: address, dtype: object

DataFrame的运算

  • DataFrame之间的运算
    同Series一样:
    在运算中自动对齐相同索引的数据
    如果索引不对应,则补NaN
#正常情况下
df1 = DataFrame(data=np.random.randint(0,10,size=(3,3)))
df2 = DataFrame(data=np.ones(shape=(3,3)))
display(df1, df2)		==>
	0	1	2
0	7	5	2
1	9	7	4
2	8	4	4

	0	1	2
0	1.0	1.0	1.0
1	1.0	1.0	1.0
2	1.0	1.0	1.0

df1 + df2	==>

0	1	2
0	8.0	6.0	3.0
1	10.0	8.0	5.0
2	9.0	5.0	5.0

#不正常情况
df3 =  DataFrame(data=np.ones(shape=(3,4)))
 如果索引不对齐,会自动补充np.nan
df1 + df3
0	1	2	3
0	8.0	6.0	3.0	NaN
1	10.0	8.0	5.0	NaN
2	9.0	5.0	5.0	NaN

#使用add函数
df1.add(df3,fill_value=0)
	0	1	2	3
0	8.0	6.0	3.0	1.0
1	10.0	8.0	5.0	1.0
2	9.0	5.0	5.0	1.0

  • 其他操作函数

+			add()
-			sub(), subtract()
*		mul(), multiply()
/		truediv(), div(), divide()
//		floordiv()
%			mod()
**			pow()
  • Series与DataFrame之间的运算
    • 使用Python操作符:以行为单位操作(参数必须是行),对所有行都有效。(类似于numpy中二维数组与一维数组的运算,但可能出现NaN)
    • 使用pandas操作函数:
      axis=0:以列为单位操作(参数必须是列),对所有列都有效。
      axis=1:以行为单位操作(参数必须是行),对所有行都有效。
s = Series(data=np.ones(shape=4), index=list("ABCE"))
df = DataFrame(data=np.random.randint(0,10,size=(4,4)), index=list("ABCD"),columns=list("abcd"))
display(s, df)		==>
A    1.0
B    1.0
C    1.0
E    1.0
dtype: float64
a	b	c	d
A	2	0	8	0
B	5	0	9	0
C	6	9	4	5
D	1	2	9	3

# 默认DataFrame与Series运算,是以列标签对齐
df + s		==>
	A	B	C	E	a	b	c	d
A	NaN	NaN	NaN	NaN	NaN	NaN	NaN	NaN
B	NaN	NaN	NaN	NaN	NaN	NaN	NaN	NaN
C	NaN	NaN	NaN	NaN	NaN	NaN	NaN	NaN
D	NaN	NaN	NaN	NaN	NaN	NaN	NaN	NaN

#axis="index" 设置以行索引对齐
df.add(s, axis="index")		==>
	a	b	c	d
A	3.0	1.0	9.0	1.0
B	6.0	1.0	10.0	1.0
C	7.0	10.0	5.0	6.0
D	NaN	NaN	NaN	NaN
E	NaN	NaN	NaN	NaN
#过滤空值
df1[df1.notnull().any(axis=1)]
	a	b	c	d
A	3.0	1.0	9.0	1.0
B	6.0	1.0	10.0	1.0
C	7.0	10.0	5.0	6.0
axis=00 == index 行):以列为单位操作(参数必须是列),对所有列都有效。 axis=11 == columns 列):以行为单位操作(参数必须是行),对所有行都有效。
【注意】fill_value在df和series之间运算时,不能使用

处理丢失数据NaN

  • 有两种丢失数据:
    • None
    • np.nan(NaN)
  • 区别:
    • type(None)是NoneType对象类型,type(np.nan)是float类型
    • None不能运算,np.nan可以运算
    • 数据运算速度,nan明显高于None,计算不同数据类型求和时间
      %timeit np.arange(1e5,dtype=xxx).sum()
  • pandas中None与np.nan都视作np.nan,自动转化

pandas中None与np.nan的操作

  • 判断函数
    • isnull()
    • notnull()
s  = 
A    28.0
B    23.0
C     NaN
D    65.0
E    90.0
Name: a, dtype: float64

s.isnull().any() 	==>True
# DataFrame中,any\all\sum\mean\std函数,需要指定方向
# 使用axis控制方向,可以查看行或列是否存在空值
df		==>
	 0	1	2
0	NaN	8	1
1	1.0	5	2
2	0.0	0	4
df.isnull().any(axis=1)		==>
0     True
1    False
2    False
dtype: bool

  • 过滤函数 dropna()
    df.dropna(axis=0, how=‘any’, thresh=None, subset=None, inplace=False)
    • axis 用于控制行或列
    • how =any 默认是有一个空值,就过滤掉该行(列)
df  ==>
a	b	c	d	e
A	66.0	51.0	31.0	NaN	6.0
B	34.0	NaN	93.0	NaN	34.0
C	NaN	NaN	100.0	NaN	NaN
D	45.0	1.0	68.0	NaN	76.0
E	53.0	26.0	87.0	NaN	NaN

df.dropna(axis=1, how="all")		==>删除d列数据
  • 填充函数 Series/DataFrame fillna()
    df.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)
    • value 指定一个特殊的值填充
    • method 指定填充方式(上 ‘backfill’, 左’bfill’,右 ‘pad’,下 ‘ffill’, None)
    • limit 限制填充次数
    • axis=1表示横向填充, 默认填充到不能填充为止
df		==>
	a	b	c	d	e
A	28.0	86.0	98.0	NaN	82.0
B	23.0	NaN	59.0	NaN	44.0
C	NaN	NaN	100.0	NaN	NaN
D	65.0	87.0	84.0	NaN	57.0
E	90.0	36.0	97.0	NaN	NaN

# 1. 指定一个特殊的值填充
# value 指要填充的固定值
df.fillna(value = 1000)	==>
a	b	c	d	e
A	28.0	86.0	98.0	1000.0	82.0
B	23.0	1000.0	59.0	1000.0	44.0
C	1000.0	1000.0	100.0	1000.0	1000.0
D	65.0	87.0	84.0	1000.0	57.0
E	90.0	36.0	97.0	1000.0	1000.0
# 2. 用相邻值填充 
df.fillna(axis=1, method="ffill")
a	b	c	d	e
A	28.0	86.0	98.0	98.0	82.0
B	23.0	23.0	59.0	59.0	44.0
C	NaN	NaN	100.0	100.0	100.0
D	65.0	87.0	84.0	84.0	57.0
E	90.0	36.0	97.0	97.0	97.0

# 3limit限制填充次数
df.fillna(axis=0, method="backfill",limit=1)
  • 指定索引标签来删除行(列)df.drop()
    df.drop(labels, axis=0, level=None, inplace=False, errors=‘raise’)
df   ==>
a	b	c	d	e
A	6.0	94.0	41.0	NaN	13.0
B	64.0	NaN	99.0	NaN	91.0
C	1.0	NaN	100.0	NaN	NaN
D	12.0	43.0	98.0	NaN	89.0
E	35.0	71.0	49.0	NaN	NaN

# 默认删除行,用列表指定行索引
df.drop(labels=["C"])

#删除列
df.drop(labels=["d","c"],axis=1)

# 删除全是空值的列
df.drop(labels=df.loc[:,df.isnull().all()].columns, axis=1)

# 删除包含空值的行
drop_index = df[df.isnull().any(axis=1)].index
df.drop(labels=drop_index)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值