Pandas的数据结构
import pandas as pd
from pandas import Series,DataFrame
import numpy as np
1、Series
Series是一种类似与一维数组的对象,由下面两个部分组成:
- values:一组数据(ndarray类型)
- index:相关的数据索引标签
#Series 其实是对ndarray的一个封装(包装)
#index: 索引
#values:值,是一个(一维的ndarray)
1)Series的创建
两种创建方式:
(1) 由列表或numpy数组创建
默认索引为0到N-1的整数型索引
nd = np.array([1,2,3])
nd
array([1, 2, 3])
s = Series([1,2,3])
s
0 1
1 2
2 3
dtype: int64
s = Series(nd, index=list("abc"))
s[0]
#注意index 索引传值的时候是一个list
1
s = Series(nd, index = ["a","b","c"])
s
a 1
b 2
c 3
dtype: int64
#咱们的索引值可不可以相同
s = Series(nd, index = list("AAA"))
s
A 1
A 2
A 3
dtype: int64
s["A"]
A 1
A 2
A 3
dtype: int64
还可以通过设置index参数指定索引
s
A 1
A 2
A 3
dtype: int64
特别地,由ndarray创建的是引用,而不是副本。对Series元素的改变也会改变原来的ndarray对象中的元素。(列表没有这种情况)
nd = np.array([0,2,4,6])
s = Series(nd, index = list("ABCD"))
s
A 0
B 2
C 4
D 6
dtype: int64
s['C'] = 16
s
A 0
B 2
C 16
D 6
dtype: int64
nd
array([ 0, 2, 16, 6])
(2) 由字典创建
s = Series(data = {"a":10,"pi":3.14,"e":2.713,"g":0.618}, index =["a","pi","e","g","kk"])
s
#假如使用字典的时候,index可以多出来值,但是数据会补上Nan
a 10.000
pi 3.140
e 2.713
g 0.618
kk NaN
dtype: float64
============================================
练习1:
使用多种方法创建以下Series,命名为s1:
语文 150
数学 150
英语 150
理综 300
============================================
s1 = Series(data = {"语文":93,"数学":79,"英语":120,"理综":20})
s1
语文 93
数学 79
英语 120
理综 20
dtype: int64
2)Series的索引和切片
可以使用中括号取单个索引(此时返回的是元素类型),或者中括号里一个列表取多个索引(此时返回的仍然是一个Series类型)。分为显示索引和隐式索引:
(1) 显式索引:
- 使用index中的元素作为索引值
- 使用.loc[](推荐)
注意,此时是闭区间
s
a 10.000
pi 3.140
e 2.713
g 0.618
kk NaN
dtype: float64
s["e"]
#返回的是float
2.713
s[["a","g"]]
#Series
a 10.000
g 0.618
dtype: float64
s1 = s.loc[["a","g"]]
s1
#使用loc取多个的值
a 10.000
g 0.618
dtype: float64
#取单个的值
s.loc["a"]
#float
10.0
type(s.loc[["a"]])
#Series
pandas.core.series.Series
(2) 隐式索引:
- 使用整数作为索引值
- 使用.iloc[](推荐)
注意,此时是半开区间
s
a 10.000
pi 3.140
e 2.713
g 0.618
kk NaN
dtype: float64
s[0]
10.0
s.iloc[0]
#在使用iloc的时候 必须穿的值是隐藏起来的索引值(也就是整型的)
10.0
s.iloc[[0,1,2]]
#取多个值的时候,加两个中括号
a 10.000
pi 3.140
e 2.713
dtype: float64
#切片
s["a":"g"]
#左闭右闭
a 10.000
pi 3.140
e 2.713
g 0.618
dtype: float64
s.loc["a":"g"]
a 10.000
pi 3.140
e 2.713
g 0.618
dtype: float64
s.iloc[0:3]
#在使用iloc的时候,左闭右开
a 10.000
pi 3.140
e 2.713
dtype: float64
============================================
练习2:
使用多种方法对练习1创建的Series s1进行索引和切片:
索引:
数学 150
切片:
语文 150
数学 150
英语 150
============================================
3)Series的基本概念
可以把Series看成一个定长的有序字典
可以通过shape,size,index,values等得到series的属性
s
a 10.000
pi 3.140
e 2.713
g 0.618
kk NaN
dtype: float64
s.shape
(5,)
s.size
5
s.index
Index(['a', 'pi', 'e', 'g', 'kk'], dtype='object')
s.values
#打印出来的数据是一个ndarray
array([10. , 3.14 , 2.713, 0.618, nan])
可以通过head(),tail()快速查看Series对象的样式
#扩展
data = pd.read_csv("./president_heights.csv")
type(data)
pandas.core.frame.DataFrame
data
order | name | height(cm) | |
---|---|---|---|
0 | 1 | George Washington | 189 |
1 | 2 | John Adams | 170 |
2 | 3 | Thomas Jefferson | 189 |
3 | 4 | James Madison | 163 |
4 | 5 | James Monroe | 183 |
5 | 6 | John Quincy Adams | 171 |
6 | 7 | Andrew Jackson | 185 |
7 | 8 | Martin Van Buren | 168 |
8 | 9 | William Henry Harrison | 173 |
9 | 10 | John Tyler | 183 |
10 | 11 | James K. Polk | 173 |
11 | 12 | Zachary Taylor | 173 |
12 | 13 | Millard Fillmore | 175 |
13 | 14 | Franklin Pierce | 178 |
14 | 15 | James Buchanan | 183 |
15 | 16 | Abraham Lincoln | 193 |
16 | 17 | Andrew Johnson | 178 |
17 | 18 | Ulysses S. Grant | 173 |
18 | 19 | Rutherford B. Hayes | 174 |
19 | 20 | James A. Garfield | 183 |
20 | 21 | Chester A. Arthur | 183 |
21 | 23 | Benjamin Harrison | 168 |
22 | 25 | William McKinley | 170 |
23 | 26 | Theodore Roosevelt | 178 |
24 | 27 | William Howard Taft | 182 |
25 | 28 | Woodrow Wilson | 180 |
26 | 29 | Warren G. Harding | 183 |
27 | 30 | Calvin Coolidge | 178 |
28 | 31 | Herbert Hoover | 182 |
29 | 32 | Franklin D. Roosevelt | 188 |
30 | 33 | Harry S. Truman | 175 |
31 | 34 | Dwight D. Eisenhower | 179 |
32 | 35 | John F. Kennedy | 183 |
33 | 36 | Lyndon B. Johnson | 193 |
34 | 37 | Richard Nixon | 182 |
35 | 38 | Gerald Ford | 183 |
36 | 39 | Jimmy Carter | 177 |
37 | 40 | Ronald Reagan | 185 |
38 | 41 | George H. W. Bush | 188 |
39 | 42 | Bill Clinton | 188 |
40 | 43 | George W. Bush | 182 |
41 | 44 | Barack Obama | 185 |
#一个DataFrame就是由多个Series组成的!!1
s_height = data['height(cm)']
type(s_height)
pandas.core.series.Series
s_height.head(2)
#head方法 取数据的前五条,而且还可以传参自定义出来的数据
0 189
1 170
Name: height(cm), dtype: int64
s_height.tail()
#tail方法,去最后的五条数据
37 185
38 188
39 188
40 182
41 185
Name: height(cm), dtype: int64
当索引没有对应的值时,可能出现缺失数据显示NaN(not a number)的情况
s = Series(data = {"a":10,"b":20,"c":30}, index =list("abcd"))
s
a 10.0
b 20.0
c 30.0
d NaN
dtype: float64
可以使用pd.isnull(),pd.notnull(),或自带isnull(),notnull()函数检测缺失数据
#后面会用到
pd.isnull(s)
a False
b False
c False
d True
dtype: bool
ind = s.isnull()
ind
a False
b False
c False
d True
dtype: bool
#使用ind给空值赋值,后面会用到
s[ind] = 1000
s
a 10.0
b 20.0
c 30.0
d 1000.0
dtype: float64
pd.notnull(s)
a True
b True
c True
d True
dtype: bool
s.notnull()
a True
b True
c True
d True
dtype: bool
Series对象本身及其实例都有一个name属性
s =Series(data = np.random.randint(0,150,size = 5), index = ["张三","李四","Lisa","Sara","Jack"])
s
张三 115
李四 95
Lisa 110
Sara 5
Jack 17
dtype: int64
s.name = "Python"
s
张三 115
李四 95
Lisa 110
Sara 5
Jack 17
Name: Python, dtype: int64
s =Series(data = np.random.randint(0,150,size = 5), index = ["张三","李四","Lisa","Sara","Jack"], name = "Math")
s
张三 81
李四 66
Lisa 145
Sara 49
Jack 4
Name: Math, dtype: int64
#扩展
df = pd.read_csv("./president_heights.csv")
s2 = df["order"]
s2
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12
12 13
13 14
14 15
15 16
16 17
17 18
18 19
19 20
20 21
21 23
22 25
23 26
24 27
25 28
26 29
27 30
28 31
29 32
30 33
31 34
32 35
33 36
34 37
35 38
36 39
37 40
38 41
39 42
40 43
41 44
Name: order, dtype: int64
4)Series的运算
(1) 适用于numpy的数组运算也适用于Series
s
张三 81
李四 66
Lisa 145
Sara 49
Jack 4
Name: Math, dtype: int64
s2 = s + 50
s2
张三 131
李四 116
Lisa 195
Sara 99
Jack 54
Name: Math, dtype: int64
s.add(20)
张三 101
李四 86
Lisa 165
Sara 69
Jack 24
Name: Math, dtype: int64
(2) Series之间的运算
-
在运算中自动对齐不同索引的数据
-
如果索引不对应,则补NaN
-
注意:要想保留所有的index,则需要使用.add()函数
s3 = s1.add(s2,fill_value = 1)
s3
Jack 55.000
Lisa 196.000
Sara 100.000
a 11.000
g 1.618
张三 132.000
李四 117.000
dtype: float64
s1 = Series(np.random.randint(0,150,size =4), index = ["A","B","C","Sara"], name = "数学")
s1
A 27
B 107
C 48
Sara 70
Name: 数学, dtype: int64
s2
张三 131
李四 116
Lisa 195
Sara 99
Jack 54
Name: Math, dtype: int64
np.nan
nan
113 + np.nan
nan
s1 + s2
#s1 里面有A 值 113 s2没有A值 Nan
A NaN
B NaN
C NaN
Jack NaN
Lisa NaN
Sara 169.0
张三 NaN
李四 NaN
dtype: float64
============================================
练习3:
-
想一想Series运算和ndarray运算的规则有什么不同?
-
新建另一个索引包含“文综”的Series s2,并与s2进行多种算术操作。思考如何保存所有数据。
============================================
nd1 = np.array([0,1,2])
nd2 = np.array([4,5,6])
nd1 + nd2
array([4, 6, 8])
2、DataFrame
DataFrame是一个【表格型】的数据结构,可以看做是【由Series组成的字典】(共用同一个索引)。DataFrame由按一定顺序排列的多列数据组成。设计初衷是将Series的使用场景从一维拓展到多维。DataFrame既有行索引,也有列索引。
- 行索引:index
- 列索引:columns
- 值:values(numpy的二维数组)
#重点
1)DataFrame的创建
最常用的方法是传递一个字典来创建。DataFrame以字典的键作为每一【列】的名称,以字典的值(一个数组)作为每一列。
此外,DataFrame会自动加上每一行的索引(和Series一样)。
同Series一样,若传入的列与字典的键不匹配,则相应的值为NaN。
import pandas as pd
from pandas import Series,DataFrame
#创建 第一种写法
df1 = DataFrame(data = {"Python":[99,101,120,98], "数学":[120,136,141,123],"语文":[98,78,99,101]}, index = list("abcd"))
df1
#这种情况是行索引多的的话会报错
Python | 数学 | 语文 | |
---|---|---|---|
a | 99 | 120 | 98 |
b | 101 | 136 | 78 |
c | 120 | 141 | 99 |
d | 98 | 123 | 101 |
df1 = DataFrame(data = {"Python":[99,101,120,98], "数学":[120,136,141,123],"语文":[98,78,99,101]},index = list("abcd"),
columns = ["Python","数学","语文","英语"])
df1
Python | 数学 | 语文 | 英语 | |
---|---|---|---|---|
a | 99 | 120 | 98 | NaN |
b | 101 | 136 | 78 | NaN |
c | 120 | 141 | 99 | NaN |
d | 98 | 123 | 101 | NaN |
#列更加重要点
DataFrame属性:values、columns、index、shape
df1.values
array([[99, 120, 98, nan],
[101, 136, 78, nan],
[120, 141, 99, nan],
[98, 123, 101, nan]], dtype=object)
df1.columns
#列索引
Index(['Python', '数学', '语文', '英语'], dtype='object')
df1.index
Index(['a', 'b', 'c', 'd'], dtype='object')
df1.shape
(4, 4)
import numpy as np
#第二种写法
df2 = DataFrame(data = np.random.randint(0,150,size = (4,4)), index = list("abcd"), columns = ["Python","Java","PHP","Html"])
df2
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 38 | 75 | 38 |
b | 68 | 33 | 101 | 63 |
c | 86 | 92 | 139 | 35 |
d | 57 | 109 | 145 | 38 |
============================================
练习4:
根据以下考试成绩表,创建一个DataFrame,命名为df:
张三 李四
语文 150 0
数学 150 0
英语 150 0
理综 300 0
============================================
2)DataFrame的索引
(1) 对列进行索引
- 通过类似字典的方式
- 通过属性的方式
可以将DataFrame的列获取为一个Series。返回的Series拥有原DataFrame相同的索引,且name属性也已经设置好了,就是相应的列名。
df2
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 38 | 75 | 38 |
b | 68 | 33 | 101 | 63 |
c | 86 | 92 | 139 | 35 |
d | 57 | 109 | 145 | 38 |
df2["Python"]
a 82
b 68
c 86
d 57
Name: Python, dtype: int64
df2.Python
#columns 列名 属性名
a 82
b 68
c 86
d 57
Name: Python, dtype: int64
df2[["Python","Java"]]
Python | Java | |
---|---|---|
a | 82 | 38 |
b | 68 | 33 |
c | 86 | 92 |
d | 57 | 109 |
#切片
df2["a":"c"]
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 38 | 75 | 38 |
b | 68 | 33 | 101 | 63 |
c | 86 | 92 | 139 | 35 |
(2) 对行进行索引
- 使用.loc[]加index来进行行索引
- 使用.iloc[]加整数来进行行索引
同样返回一个Series,index为原来的columns。
df2.loc["a"]
#Series
Python 82
Java 38
PHP 75
Html 38
Name: a, dtype: int64
df2.loc[["a"]]
#DataFrame数据
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 38 | 75 | 38 |
df2.iloc[0]
Python 82
Java 38
PHP 75
Html 38
Name: a, dtype: int64
df2.iloc[[1]]
Python | Java | PHP | Html | |
---|---|---|---|---|
b | 68 | 33 | 101 | 63 |
df2.iloc[[1,2]]
Python | Java | PHP | Html | |
---|---|---|---|---|
b | 68 | 33 | 101 | 63 |
c | 86 | 92 | 139 | 35 |
df2.iloc[0:3]
#左闭右开
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 38 | 75 | 38 |
b | 68 | 33 | 101 | 63 |
c | 86 | 92 | 139 | 35 |
df2.loc["a"]["Java"]
38
df2.loc['a',"Java"]
#忘记这种情况吧!!!!!!
38
df2["Java"]["a"]
38
(3) 对元素索引的方法
- 使用列索引
- 使用行索引(iloc[3,1]相当于两个参数;iloc[[3,3]] 里面的[3,3]看做一个参数)
- 使用values属性(二维numpy数组)
df2["Java"]["a":"c"]
#左闭右闭
a 38
b 33
c 92
Name: Java, dtype: int64
df2.iloc[1:3]["Html"]
#左闭右开
b 63
c 35
Name: Html, dtype: int64
df2.loc["a","Python"]
82
df2.loc[["a","b"], "Python"]
#loc是一个非常特殊的方法
a 82
b 68
Name: Python, dtype: int64
df2.loc['a':"b", "Python"]
a 82
b 68
Name: Python, dtype: int64
#赋值
df2["Python"]["b"] += 50
df2
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 38 | 75 | 38 |
b | 118 | 33 | 101 | 63 |
c | 86 | 92 | 139 | 35 |
d | 57 | 109 | 145 | 38 |
df2.loc["a":"c", "Java"] += 20
df2
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 58 | 75 | 38 |
b | 118 | 53 | 101 | 63 |
c | 86 | 112 | 139 | 35 |
d | 57 | 109 | 145 | 38 |
【注意】
直接用中括号时:
- 索引表示的是列索引
- 切片表示的是行切片
df2["a":"b"]
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 58 | 75 | 38 |
b | 118 | 53 | 101 | 63 |
df2["Python"]
a 82
b 118
c 86
d 57
Name: Python, dtype: int64
============================================
练习5:
使用多种方法对ddd进行索引和切片,并比较其中的区别
============================================
3)DataFrame的运算
(1) DataFrame之间的运算
同Series一样:
- 在运算中自动对齐不同索引的数据
- 如果索引不对应,则补NaN
df1
Python | 数学 | 语文 | 英语 | |
---|---|---|---|---|
a | 99 | 120 | 98 | NaN |
b | 101 | 136 | 78 | NaN |
c | 120 | 141 | 99 | NaN |
d | 98 | 123 | 101 | NaN |
df2
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 58 | 75 | 38 |
b | 118 | 53 | 101 | 63 |
c | 86 | 112 | 139 | 35 |
d | 57 | 109 | 145 | 38 |
df1 + df2
Html | Java | PHP | Python | 数学 | 英语 | 语文 | |
---|---|---|---|---|---|---|---|
a | NaN | NaN | NaN | 181 | NaN | NaN | NaN |
b | NaN | NaN | NaN | 219 | NaN | NaN | NaN |
c | NaN | NaN | NaN | 206 | NaN | NaN | NaN |
d | NaN | NaN | NaN | 155 | NaN | NaN | NaN |
df1.add(df2, fill_value = 0)
Html | Java | PHP | Python | 数学 | 英语 | 语文 | |
---|---|---|---|---|---|---|---|
a | 38.0 | 58.0 | 75.0 | 181 | 120.0 | NaN | 98.0 |
b | 63.0 | 53.0 | 101.0 | 219 | 136.0 | NaN | 78.0 |
c | 35.0 | 112.0 | 139.0 | 206 | 141.0 | NaN | 99.0 |
d | 38.0 | 109.0 | 145.0 | 155 | 123.0 | NaN | 101.0 |
df1 = DataFrame(np.random.randint(0,150,size = (4,2)),
index = list("cdef"),
columns = ["Python","Java"])
df1
Python | Java | |
---|---|---|
c | 137 | 102 |
d | 118 | 97 |
e | 77 | 48 |
f | 38 | 24 |
df2
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 58 | 75 | 38 |
b | 118 | 53 | 101 | 63 |
c | 86 | 112 | 139 | 35 |
d | 57 | 109 | 145 | 38 |
df1.add(df2, axis = "index", fill_value = 0)
#出现第一个bug axis 在这个地方显示不出来!!!!!
Html | Java | PHP | Python | |
---|---|---|---|---|
a | 38.0 | 58.0 | 75.0 | 82.0 |
b | 63.0 | 53.0 | 101.0 | 118.0 |
c | 35.0 | 214.0 | 139.0 | 223.0 |
d | 38.0 | 206.0 | 145.0 | 175.0 |
e | NaN | 48.0 | NaN | 77.0 |
f | NaN | 24.0 | NaN | 38.0 |
下面是Python 操作符与pandas操作函数的对应表:
Python Operator | Pandas Method(s) |
---|---|
+ |
add() |
- |
sub() , subtract() |
* |
mul() , multiply() |
/ |
truediv() , div() , divide() |
// |
floordiv() |
% |
mod() |
** |
pow() |
(2) Series与DataFrame之间的运算
【重要】
-
使用Python操作符:以行为单位操作(参数必须是行),对所有行都有效。(类似于numpy中二维数组与一维数组的运算,但可能出现NaN)
-
使用pandas操作函数:
axis=0:以列为单位操作(参数必须是列),对所有列都有效。 axis=1:以行为单位操作(参数必须是行),对所有行都有效。
df2
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 58 | 75 | 38 |
b | 118 | 53 | 101 | 63 |
c | 86 | 112 | 139 | 35 |
d | 57 | 109 | 145 | 38 |
s_row = df2.loc['c']
s_row
#Series
Python 86
Java 112
PHP 139
Html 35
Name: c, dtype: int64
s_columns = df2["Python"]
s_columns
a 82
b 118
c 86
d 57
Name: Python, dtype: int64
df2
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 82 | 58 | 75 | 38 |
b | 118 | 53 | 101 | 63 |
c | 86 | 112 | 139 | 35 |
d | 57 | 109 | 145 | 38 |
df2.add(s_columns,axis = 0)
#s_columns
#a 48
# b 78
# c 68
# d 70
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 164 | 140 | 157 | 120 |
b | 236 | 171 | 219 | 181 |
c | 172 | 198 | 225 | 121 |
d | 114 | 166 | 202 | 95 |
df2.add(s_columns,axis = "index")
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 164 | 140 | 157 | 120 |
b | 236 | 171 | 219 | 181 |
c | 172 | 198 | 225 | 121 |
d | 114 | 166 | 202 | 95 |
df2.add(s_row,axis = "columns")
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 168 | 170 | 214 | 73 |
b | 204 | 165 | 240 | 98 |
c | 172 | 224 | 278 | 70 |
d | 143 | 221 | 284 | 73 |
df2 + s_row
Python | Java | PHP | Html | |
---|---|---|---|---|
a | 168 | 170 | 214 | 73 |
b | 204 | 165 | 240 | 98 |
c | 172 | 224 | 278 | 70 |
d | 143 | 221 | 284 | 73 |
#DataFrame和Series进行运算的时候要严格注意 axis
#Series,是一个一维的数据,DataFrame 是一个多维的数据索引不对齐的话肯定会出现错误
============================================
练习6:
-
假设ddd是期中考试成绩,ddd2是期末考试成绩,请自由创建ddd2,并将其与ddd相加,求期中期末平均值。
-
假设张三期中考试数学被发现作弊,要记为0分,如何实现?
-
李四因为举报张三作弊立功,期中考试所有科目加100分,如何实现?
-
后来老师发现有一道题出错了,为了安抚学生情绪,给每位学生每个科目都加10分,如何实现?
============================================