赞
踩
目录
对于组合数据类型:
例:将构成一个学生整体的数据类型对象
numpy.ones_like()
#注意:对于浮点参数(参数为浮点),结果的长度为(stop - start)/ step)由于浮点溢出,此规则可能导致最后一个元素大于stop。因此要特别注意
- import numpy as np
- [in]: a = [1, 2, 3, 4]
- [in]: new_arr = np.asarray(a)
- [in]: print(new_arr)
- [out]: [1 2 3 4]
-
- [in]: new_arr = np.asarray(a , dtype=np.float32)
- [in]: print(new_arr)
- [out]: [1. 2. 3. 4.]
numpy.frombuffer 用于实现动态数组,将数据以流的形式读入转化成ndarray对象
- import numpy as np
-
- [in]: s = b'Hello World' #buffer 是字符串的时候,Python3 默认 str 是 Unicode 类型,所以要转成 bytestring 在原 str 前加上 b
- [in]: a = np.frombuffer(s, dtype = 'S1')
- [in]: print (a)
- [out]: [b'H' b'e' b'l' b'l' b'o' b' ' b'W' b'o' b'r' b'l' b'd']
numpy.random
模块生成数组总体来说,
numpy.random
模块分为四个部分,对应四种功能:
简单随机数: 产生简单的随机数据,可以是任何维度
排列:将所给对象随机排列
分布:产生指定分布的数据,如高斯分布等
生成器:种随机数种子,根据同一种子产生的随机数是相同的
相当于就是将slice的第一个参数当做切片的start,第二个参数当做切片的end,第三个参数当做切片的步长
对于一维数组(直接当做list看)
- [in]: x = np.arange(10)
- [in]: y = x[2:8:3]
- [in]: print(y)
[out]: [2 5]
推广至二维:(中间利用逗号,进行分隔,第一部分参数是表示第一个维度,第二部分参数表示第二个维度),根据axis总结的相关知识,第一个维度管理的是沿着其变化方向如(0,0)->(1,0)可知,第一个维度管理的是每一层,所以此处对每一层是不会进行切割处理的。同理,我们看第二个维度,(0,0)->(0,1)沿着列方向向下变化,管理每一个列,于是切割到只剩下index=2的一列
python的 list 的切片返回是原数据的副本,即开辟了一个新的内存地址储存数据,因此修改切片出来的结果,原数据并不会发生改变。
而numpy 以效率为主,所以 numpy 的切片返回的是原数据的视图,即不会创建新的内存地址,而是对原数据内存地址的引用。所以对numpy 切片结果进行修改会发现,原数据也一起发生了改变。
注意:numpy 中所有的运算操作符都不会为数组创建副本
- [in]: x = np.arange(1,10).reshape(3,-1) #创建一个3 * 3大小的二维数组
- #解释一下,上行代码的-1的作用:前面生成9个元素,axis=1位置-1自动9/3=3
- [in]: print(x)
- [out]: [[1 2 3]
- [4 5 6]
- [7 8 9]]
-
- [in]: y = x[:2,:2]
- [in]: print(y)
- [out]: [[1 2]
- [4 5]]
-
- [in]: y[1,1] = 999
- [in]: print(y)
- [out]: [[ 1 2]
- [ 4 999]]
-
- [in]: print(x)
- [out]: [[ 1 2 3]
- [ 4 999 6]
- [ 7 8 9]]
注意:对于索引数组的所有情况,返回的是原始数据的副本,而不是切片获取的视图。
- # x = [10 9 8 7 6 5 4 3 2]
- [in]: y = x[np.array([3,3,-3,8])]
- [in]: print(y)
- [out]: [7 7 4 2]
推广至多维:(np.array中的元素构成单一索引值,一一映射到x中,并进行相应的替换。)
- # x = [10 9 8 7 6 5 4 3 2]
- [in]: y = x[np.array([[1,1],[2,3]])]
- [in]: print(y)
- [out]: array([[9, 9],
- [8, 7]])
验证索引用的是副本,而不是视图!!!
很显然92没有被改变
推广至二维:
广播机制的应用:
Numpy 的广播机制先将[2]变成[2, 2],然后再拼接成相应的下标
arr[0, 2]
和arr[1, 2]
。
其他例子:
In a nutshell:
- import numpy
-
- arr_1 = numpy.arange(1, 7).reshape((2, 3))
- arr_2 = numpy.arange(7, 13).reshape((2, 3))
- arr_3 = numpy.arange(13, 19).reshape((2, 3))
- arr_4 = numpy.arange(19, 25).reshape((2, 3))
-
- print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=0))
- print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=0).shape)
-
- print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=1))
- print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=1).shape)
-
- print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=2))
- print(numpy.stack([arr_1, arr_2, arr_3, arr_4], axis=2).shape)
输出:
需要注意的是:axis 等于几就说明在哪个维度上进行堆叠。
当 axis=0 的时候,意味着整体,也就是一个2行3列的数组。所以对于0维堆叠,相当于简单的物理罗列,比如这四个数组代表的是4张图像的数据,进行0维堆叠也就是把它们按顺序排放了起来,形成了一个(4,2,3)的3维数组。
当 axis=1 的时候,意味着第一个维度,也就是数组的每一行。所以对于1维堆叠,4个2行3列的数组,各自拿出自己的第一行数据进行堆叠形成3维数组的第一“行”,各自拿出自己的第二行数据进行堆叠形成3维数组的第二“行”,从而形成了一个(2,4,3)的3维数组。
当 axis=2 的时候,意味着第二个维度,注意:千万不要理解成2维堆叠是对每一列拿出来进行堆叠!这个堆叠是对于整个维度来讲的,我们把一维空间理解为一条线,而二维空间则是一个平面。从第二个维度堆叠可以看作平面与平面的堆叠。
- import numpy as np
-
- arr = np.arange(9)
- print(arr)
-
- arr_1 = np.split(arr, 3)
- arr_2 = np.split(arr, [4, 7])
- print(arr_1)
- print(arr_2)
-
- '''output:
- [0 1 2 3 4 5 6 7 8]
- [array([0, 1, 2]), array([3, 4, 5]), array([6, 7, 8])]
- [array([0, 1, 2, 3]), array([4, 5, 6]), array([7, 8])]
对应位置,依次进行相关的操作!!!
如果两个数组的后缘维度(trailing dimension,即从末尾开始算起的维度)的轴长度相符,或其中的一方的长度为1,则认为它们是广播兼容的。广播会在缺失和(或)长度为1的维度上进行。
通俗的解释一下就是广播机制可以在两种情况下作用,一种是两个数组的维数不相等,但是它们的后缘维度的轴长相符(其实就是从后数的连续若干个维度数都相同),另外一种是有一方的长度为1(其实就是如果从后数有维度不同,但是维度大小为1时,广播机制同样可以发挥作用)。
(a)后锥维度的轴长相符
(b) 后缘维度不全相同,有一方长度为1
(c)反例
NumPy 的 copy 操作分为三种:无拷贝、浅拷贝、深拷贝。每种拷贝方式的机制和内存操作有所区别,可以联系到我们之前学过的视图和副本的内容,如果使用不当可以浪费大量内存,因此要理解操作中的各种行为,根据实际情况选择最合理的方法。
可以看到 a 和 b 并不同属一块内存,是两个不同的对象。然而对 b 的修改会改变 a ,证明其实浅拷贝操作还是共用的一个底层数据。
虽然改b的值会同步更新到a,但是改动b的形状是不会反映到a的!!!
- #1.从列表创建
- s1 = pd.Series([1, 2, 3, 4, 5])
- #2.从 ndarray 创建
- s2 = pd.Series(np.arange(5), index=['a','b','c','d','e'])
- #3.从字典创建
- temp_dict = {"name": "zhangsan", "age": 27, "tel": 10086}
- s3 = pd.Series(temp_dict)
- #4.从标量值构造
- s4 = pd.Series(1., index=list("abcde"))
输出:
对于上面两个不能完全对齐的
Series
,结果的index
是两者的并集,同时不能对齐的部分当作缺失值处理.
- # 创建一个带缺失值Series
- s = pd.Series([1, 2, None, 4, None])
- # 检测缺失值
- print(s.isna())
- '''Output:
- 0 False
- 1 False
- 2 True
- 3 False
- 4 True
- dtype: bool'''
- # 填充缺失值,填充值为0.
- print(s.fillna(0.))
- '''Output:
- 0 1.0
- 1 2.0
- 2 0.0
- 3 4.0
- 4 0.0
- dtype: float64'''
(i)可以在定义时指定
name
属性:
s = pd.Series(np.arange(5), name="something") print(s.name) '''[out]: something'''(ii)通过
Series.index
查看索引, 通过values
查看值
s = pd.Series(np.arange(5), index=list("abcde")) print(s.index) '''[out]: Index(['a', 'b', 'c', 'd', 'e'], dtype='object')''' print(s.values) '''[out]: [0 1 2 3 4]'''
DataFrame
是pandas
中的二维数据结构,可以看成一个 Excel 中的工作表,或者一个 SQL 表,或者一个存储Series
对象的字典,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。
DataFrame
既有行索引也有列索引,它可以被看做由Series
组成的字典(共同用一个索引),其中的index
用于指定行的label
,columns
用于指定列的label
,如果参数不传入,那么会按照传入的内容进行设定。
两大类创建方式(①从列表(单个+嵌套)②从字典(数组or列表))
- #1.1使用单个列表创建
- data = [1, 2, 3, 4, 5]
- df = pd.DataFrame(data)
- print(df)
- '''[out]:
- 0
- 0 1
- 1 2
- 2 3
- 3 4
- 4 5'''
- #1.2使用嵌套列表创建并指定列索引
- data = [['xiaoming', 10], ['xiaohong', 11], ['xiaozhang', 12]]
- df = pd.DataFrame(data, columns=['Name', 'Age'])
- print(df)
- '''[out]:
- Name Age
- 0 xiaoming 10
- 1 xiaohong 11
- 2 xiaozhang 12'''
- #2.1从字典使用数组创建->注意:两个数据的长度必须一样
- data = {'Name': ['xiaoming', 'zhangsan', 'lisi'], 'Age':[10, 11, 21]}
- df = pd.DataFrame(data)
- print(df)
- '''[out]:
- Name Age
- 0 xiaoming 10
- 1 zhangsan 11
- 2 lisi 21'''
- #2.2从字典列表创建
- #字典列表可作为输入数据传递以用来创建 DataFrame ,
- #字典键默认为列名,缺失的部分会自动填充 NaN 值
- data = [{'a': 1, 'b': 2}, {'a': 5, 'b': 6, 'c': 7}]
- df = pd.DataFrame(data, index=["first", "second"]) # 指定行索引
- print(df)
- '''[out]:
- a b c
- first 1 2 NaN
- second 5 6 7.0'''
注:2.1的示例显然字典的键默认充当了column值!!!value
可以是各种能够转化为 Series
的对象,与 Series
要求所有的类型都一致不同,DataFrame
值要求每一列数据的格式相同->各列数据类型用下面的df.dtypes来进行查询。
DataFrame
的基础属性
df.shape
# 形状,行数列数df.dtypes
# 列数据类型df.ndim
# 数据维度df.index
# 行索引df.columns
# 列索引df.values
# 对象值,二维ndarray
数组
DataFrame
的整体情况查询
df.head()
# 显示头部几行df.tail()
# 显示尾部几行df.info()
# 相关信息概览:行数,列数,列索引,列非空值个数,列类型,内存占用df.describe()
# 快速综合统计结果:计数,均值,标准差,最大值,四分位数,最小值
describe():示例
- print(df.describe())
- '''[out]:
- A B C D
- count 6.000000 6.000000 6.000000 6.000000
- mean 0.170426 0.204062 -0.433312 -0.112912
- std 1.831264 0.861747 1.082089 0.861061
- min -1.252650 -1.068945 -1.715116 -1.294911
- 25% -0.791367 -0.101212 -1.225638 -0.466866
- 50% -0.469743 0.061138 -0.342377 -0.222187
- 75% 0.156002 0.712040 -0.048075 0.193103
- max 3.748685 1.397363 1.270031 1.278703'''
DataFrame
支持ndarray
的索引语法,但是推荐使用.loc, .iloc .ix
方法进行索引。
- # 创建一个6行3列的正太分布结构
- df = pd.DataFrame(np.random.randn(6,4), index=list("abcdef"),
- columns=list('ABCD'))
- # 创建一个3行4列的结构
- df2 = pd.DataFrame(np.arange(12).reshape(3, 4), index=list("abc"), columns=list("WXYZ"))
- #1.1列:读取单列
- print(df["A"])
- #等效于 print(df.A)
- '''Output:
- a -2.021650
- b 0.259206
- c 0.868003
- d 0.803916
- e -0.271057
- f -1.251718
- Name: A, dtype: float64'''
- #1.2列:读取多列
- print(df[["A", "C"]])
- ''' Output:
- A C
- a -2.021650 0.659043
- b 0.259206 -0.542967
- c 0.868003 0.599239
- d 0.803916 -0.207791
- e -0.271057 -0.588037
- f -1.251718 -2.018937'''
- #2.1行:使用切片
- print(df[0:3])
- '''output:
- A B C D
- a -2.021650 -0.819054 0.659043 0.526803
- b 0.259206 -3.061188 -0.542967 -0.118463
- c 0.868003 0.460860 0.599239 1.919060'''
- #2.2行:索引读取
- print(df["a":"c"])
- ''' A B C D
- a -2.021650 -0.819054 0.659043 0.526803
- b 0.259206 -3.061188 -0.542967 -0.118463
- c 0.868003 0.460860 0.599239 1.919060'''
- #3.读取多行多列也是可以的
- print(df["a":"c"][["A", "D"]])
- ''' A D
- a -2.021650 0.526803
- b 0.259206 -0.118463
- c 0.868003 1.919060'''
.loc ->根据index和column名进行操作,.loc[...]
- # 创建一个3行4列的结构
- df2 = pd.DataFrame(np.arange(12).reshape(3, 4), index=list("abc"), columns=list("WXYZ"))
-
- #1单切:.loc 可以使用 label 进行索引
- #查询单行
- print(df2.loc["a"])
- '''W 0
- X 1
- Y 2
- Z 3
- Name: a, dtype: int32'''
- #查询多行
- print(df2.loc[["a", "c"]])
- '''W X Y Z
- a 0 1 2 3
- c 8 9 10 11'''
- #2.连续切片:“,”左边为行索引,右边为列索引
- #写法1, 离散的多行多列
- print(df2.loc[["a", "b"], ["W", "Y"]])
- '''W Y
- a 0 2
- b 4 6'''
- #写法2,连续的多行离散的多列
- print(df2.loc[df2.index[0:2], ["W", "Y"]])
- '''W Y
- a 0 2
- b 4 6'''
- #写法3,连续的多行多列
- print(df2.loc["a": "c", "W": "Y"])
- '''W X Y
- a 0 1 2
- b 4 5 6
- c 8 9 10'''
注意:loc是闭区间!!!!!
.iloc
根据位置(就是直接用数字(默认从0开始)切片or索引)读取
,也可以进行切片 ->>>补充:.ix可以综合iloc和.loc使用
- # 创建一个3行4列的结构
- df2 = pd.DataFrame(np.arange(12).reshape(3, 4), index=list("abc"), columns=list("WXYZ"))
-
- # 获取前两行->左闭右开(注意区分)
- print(df2.iloc[0:2])
- ''' W X Y Z
- a 0 1 2 3
- b 4 5 6 7'''
- # 获取前2行前3列
- print(df2.iloc[0:2, 0:3])
- ''' W X Y
- a 0 1 2
- b 4 5 6'''
- # 获取所有行,前2列
- print(df2.iloc[:, 0:2])
- '''W X
- a 0 1
- b 4 5
- c 8 9'''
- # 获取前2行,所有列
- print(df2.iloc[0:2, :])
- '''W X Y Z
- a 0 1 2 3
- b 4 5 6 7'''
- # 创建一个6行3列的正太分布结构
- df = pd.DataFrame(np.random.randn(6,4), index=list("abcdef"),
- columns=list('ABCD'))
-
- print(df > 0)
- '''A B C D
- a False False True True
- b True False False False
- c True True True True
- d True False False True
- e False False False True
- f False True False False'''
- #获取所有 A 列大于0的行:
- print(df['A'] > 0)
- '''
- a False
- b True
- c True
- d True
- e False
- f False
- Name: A, dtype: bool'''
- print(df[df['A'] > 0])
- ''' A B C D
- b 0.259206 -3.061188 -0.542967 -0.118463
- c 0.868003 0.460860 0.599239 1.919060
- d 0.803916 -1.835040 -0.207791 0.445216'''
- #也能传入多个条件,不同的条件之间需要用括号括起来
- print(df2[(df2 > 1) & (df2 < 10)])
- '''W X Y Z
- a NaN NaN 2.0 3.0
- b 4.0 5.0 6.0 7.0
- c 8.0 9.0 NaN NaN'''
在一个轴上拥有多个索引级别,另一种说法是它能以低纬度形式来处理高纬度数据。
- data = [16, 17, 21, 18, 19, 22]
- s = pd.Series(data,
- index=[["first", "first", "second", "second", "third", "third"],
- ["male", "female", "male", "female", "male", "female"]])
- print(s)
- '''output:
- first male 16
- female 17
- second male 21
- female 18
- third male 19
- female 22
- dtype: int64'''
- # 显示层次化索引
- print(s.index)
- '''MultiIndex([( 'first', 'male'),
- ( 'first', 'female'),
- ('second', 'male'),
- ('second', 'female'),
- ( 'third', 'male'),
- ( 'third', 'female')],
- )'''
Series层次索引 应用实例:
- #1.获取一下一班的男女生人数:
- # 传入第一个索引
- print(s["first"])
- '''[out]:
- male 16
- female 17
- dtype: int64'''
- #2.获取一二班的男女生人数->层次索引的切片操作
- print(s["first": "second"])
- '''[out]:
- first male 16
- female 17
- second male 21
- female 18
- dtype: int64'''
- # 也可以多项选择
- print(s[["first", "third"]])
- '''[out]:
- first male 16
- female 17
- third male 19
- female 22
- dtype: int64 '''
- #3.获取一班的男生人数
- #方式一:内外层结合选择
- print(s["first", "male"])
- #方式二:先选择外层索引,再选择内层索引
- print(s["first"]["male"])
- '''16'''
- #4.获取各班的女生人数
- #方式一:内外层结合选择
- print(s[:, "female"])
- #方式二:先选择外层索引,再选择内层索引
- print(s["first": "third"][:, "female"])
- '''[out]:
- first 17
- second 18
- third 22
- dtype: int64'''
-
对于
DataFrame
来说,行和列都能进行层次化索引,也就是四个索引决定一个值,将一个二维数据变成了一个四维数据。
我们来统计一下三个班级中数学、语文、英语三门学科男生和女生考试成绩的等级划分:
data = np.random.randint(10, 20, size=(6, 9)) # [10, 20)之间的随机整数 index = [["first", "first", "second", "second", "third", "third"], ["male", "female", "male", "female", "male", "female"]] columns = [["Ch", "Ch", "Ch", "Ma", "Ma", "Ma", "En", "En", "En"], ["A", "B", "C", "A", "B", "C", "A", "B", "C"]] df = pd.DataFrame(data, index=index, columns=columns) print(df) '''[out]: Ch Ma En A B C A B C A B C first male 18 14 12 14 18 11 18 15 11 female 13 13 15 13 16 19 12 17 19 second male 11 16 17 19 19 10 15 11 13 female 11 11 17 16 11 17 19 12 11 third male 18 18 12 16 12 19 13 19 18 female 18 14 18 19 15 18 13 18 13''' # 显示层次化索引 print(df.index) '''[out]: MultiIndex([( 'first', 'male'), ( 'first', 'female'), ('second', 'male'), ('second', 'female'), ( 'third', 'male'), ( 'third', 'female')], )''' print(df.columns) '''[out]: MultiIndex([('Ch', 'A'), ('Ch', 'B'), ('Ch', 'C'), ('Ma', 'A'), ('Ma', 'B'), ('Ma', 'C'), ('En', 'A'), ('En', 'B'), ('En', 'C')], )'''
DataFrame层次化索引 应用举例
- #各班的学生数学成绩各等级人数:
- print(df["Ma"])
- '''[out]:
- A B C
- first male 14 18 11
- female 13 16 19
- second male 19 19 10
- female 16 11 17
- third male 16 12 19
- female 19 15 18'''
- #获取一班的所有项:
- print(df.loc["first"])
- '''
- Ch Ma En
- A B C A B C A B C
- male 18 14 12 14 18 11 18 15 11
- female 13 13 15 13 16 19 12 17 19'''
- #获取一班男女生英语成绩各等级的人数
- print(df.loc["first", "En"])
- ''' A B C
- male 18 15 11
- female 12 17 19'''
- #获取各班语文成绩为 A 的人数:
- print(df["Ch"]["A"])
- '''
- first male 18
- female 13
- second male 11
- female 11
- third male 18
- female 18
- Name: A, dtype: int32'''
- #获取一班男女生的语文和英语成绩各等级人数:
- print(df.loc["first", ["Ch", "En"]])
- ''' Ch En
- A B C A B C
- male 18 14 12 18 15 11
- female 13 13 15 12 17 19'''
- #获取一班男女生的语文成绩 A 等级人数:
- print(df.loc["first", "Ch"]["A"])
- '''[out]:
- male 18
- female 13
- Name: A, dtype: int32'''
- #获取一班男生的各科成绩等级人数:
- print(df.loc["first", :].loc["male"])
- '''
- Ch A 18
- B 14
- C 12
- Ma A 14
- B 18
- C 11
- En A 18
- B 15
- C 11
- Name: male, dtype: int32'''
-
注意:
- import numpy as np
- import pandas as pd
- index=[['first','first','second','second','third','third']
- ,['male','female','male','female','male','female']]
- column=[['Ch','Ch','Ch','Ma','Ma','Ma','En','En','En',],
- ['A','B','C','A','B','C','A','B','C']]
- data=pd.DataFrame(np.random.randint(10,20,size=(6,9)),index=index,columns=column)
- print(data.loc['second',:])
- print(data.loc['second',:].loc['male'])
- print('*'*50)
- print(data.loc['second','Ma'])
- print(data.loc['second','Ma']['A'])
- #注意上面的两种写法->只有当指定外层的两个单个索引时,才能直接进行[]索引,否则需要继续loc
输出:
''' Ch Ma En A B C A B C A B C male 12 12 11 18 19 16 18 12 16 female 18 15 19 14 12 19 14 10 12 Ch A 12 B 12 C 11 Ma A 18 B 19 C 16 En A 18 B 12 C 16 Name: male, dtype: int32 ************************************************** A B C male 18 19 16 female 14 12 19 male 18 female 14 Name: A, dtype: int32 '''
Pandas
包的merge、join
方法可以完成数据的合并,merge
方法主要基于两个DataFrame
的共同列进行合并,join 方法主要基于两个DataFrame
的索引进行合并。
pandas.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=False, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)
- df1 = pd.DataFrame({'key':['s','s','w','x','x','n','f','c'], 'data1':range(8)})
- df2 = pd.DataFrame({'key':['w','w','s','s','x','f'], 'data2':range(6)})
- '''df1:
- key data1
- 0 s 0
- 1 s 1
- 2 w 2
- 3 x 3
- 4 x 4
- 5 n 5
- 6 f 6
- 7 c 7
- df2:
- key data2
- 0 w 0
- 1 w 1
- 2 s 2
- 3 s 3
- 4 x 4
- 5 f 5'''
- #1.默认情况下的合并(默认使用的是 inner 内连接方式,结果做的交集->发现有行消失了
- print(pd.merge(df1, df2))
- '''
- key data1 data2
- 0 s 0 2
- 1 s 0 3
- 2 s 1 2
- 3 s 1 3
- 4 w 2 0
- 5 w 2 1
- 6 x 3 4
- 7 x 4 4
- 8 f 6 5'''
- #2.外连接
- #outer 外连接方式,我们可以理解为基于共同列的并集进行连接,参数 on 设置链接的共有列名。
- print(pd.merge(df1, df2, how="outer", on="key"))
- ''' key data1 data2
- 0 s 0 2.0
- 1 s 0 3.0
- 2 s 1 2.0
- 3 s 1 3.0
- 4 w 2 0.0
- 5 w 2 1.0
- 6 x 3 4.0
- 7 x 4 4.0
- 8 n 5 NaN
- 9 f 6 5.0
- 10 c 7 NaN'''
- #若两个 DataFrame 间出了 on 设置的连接列外并无相同列,则该列的值置为 NaN
- #3.左连接
- #left 左连接,我们可以理解为基于左边位置的 DataFrame 的列进行连接
- print(pd.merge(df1, df2, how="left"))
- ''' key data1 data2
- 0 s 0 2.0
- 1 s 0 3.0
- 2 s 1 2.0
- 3 s 1 3.0
- 4 w 2 0.0
- 5 w 2 1.0
- 6 x 3 4.0
- 7 x 4 4.0
- 8 n 5 NaN
- 9 f 6 5.0
- 10 c 7 NaN'''
- 4.基于多列的连接
- df1 = pd.DataFrame({'key1': ['foo', 'foo', 'bar'],
- 'key2': ['one', 'two', 'one'],'val': [1, 2, 3]})
- '''key1 key2 val
- 0 foo one 1
- 1 foo two 2
- 2 bar one 3'''
- df2 = pd.DataFrame({'key1': ['foo', 'foo','bar','bar'],
- 'key2': ['one', 'one', 'one','two'],'val': [4,5,6,7]})
- '''key1 key2 val
- 0 foo one 4
- 1 foo one 5
- 2 bar one 6
- 3 bar two 7'''
- #4.1多列的右连接:
- print(pd.merge(df1, df2, on=["key1", "key2"], how="right"))
- '''key1 key2 val_x val_y
- 0 foo one 1.0 4
- 1 foo one 1.0 5
- 2 bar one 3.0 6
- 3 bar two NaN 7'''
- #多列连接只需要传入列名组成的列表就可以了
- #注意:left列表中foo two由于右列表无,所以,交之后被删去。右列表有的左没有,那也得加上去。
- 4.2当合并的数据有相同的列时,结构会默认在后面添加 _x, _y 来区分,
- 我们也可以通过 suffixes 参数来手动指定:
- print(pd.merge(df1, df2, on=["key1", "key2"], suffixes=["_left", "_right"]))
- ''' key1 key2 val_left val_right
- 0 foo one 1 4
- 1 foo one 1 5
- 2 bar one 3 6'''
DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)
- df1 = pd.DataFrame(np.arange(8).reshape(2, 4),
- index=["one", "two"], columns=list("ABCD"))
- ''' A B C D
- one 0 1 2 3
- two 4 5 6 7'''
- df2 = pd.DataFrame(np.arange(12).reshape(3, 4),
- index=["one", "two", "three"], columns=list("CDEF"))
- ''' W X Y Z
- one 0 1 2 3
- two 4 5 6 7
- three 8 9 10 11'''
- #1.默认情况下的join
- # 未指定合并的列,默认选取两者重复的列
- print(df1.join(df2))
- ''' A B C D W X Y Z
- one 0 1 2 3 0 1 2 3
- two 4 5 6 7 4 5 6 7'''
- #2.df2.join(df1)
- df2.join(df1)
- ''' W X Y Z A B C D
- one 0 1 2 3 0.0 1.0 2.0 3.0
- two 4 5 6 7 4.0 5.0 6.0 7.0
- three 8 9 10 11 NaN NaN NaN NaN'''
- #可见会以前者的索引为基准来进行合并,并且不足的地方会自动填充 NaN 值,超出的地方会自动删除
DataFrame.groupby(by=None, axis=0, level=None, as_index=True, sort=True, group_keys=True, squeeze=<no_default>, observed=False, dropna=True)
参数说明:
by
:接收list,string,mapping,generator
,用于确定分组的依据,无默认。axis
:接收int
,表示操作的轴向,默认为0,对列进行操作。level
:接收int
或者索引名,代表标签所在级别。as_index
:表示聚合后的聚合标签是否以DataFrame
索引形式输出,默认为True
。sort
:表示是否对分组依据分组标签进行排序。group_keys
:表示是否显示分组标签的名称。squeeze
:表示是否在允许的情况下对返回数据进行降维。
更加详细的 API 描述可以查阅官方文档 pandas.DataFrame.groupby
我们先来创建一个 DataFrame
,包含课程,等级,和男女生人数信息:
- # 用字典创建DataFrame
- [in]: data = {"lessons": ['Ch', 'En', 'Ch', 'En', 'Ch', 'Ma', 'En', 'Ma'],
- "grade": ['A', 'A', 'B', 'B', 'C', 'A', 'C', 'B'],
- "male": np.random.randint(10, 20, 8), # [10, 20)的8个随机整数
- "female": np.random.randint(10, 20, 8)}
- [in]: df = pd.DataFrame(data)
- [in]: print(df)
- [out]:
- lessons grade male female
- 0 Ch A 14 17
- 1 En A 10 11
- 2 Ch B 11 11
- 3 En B 15 12
- 4 Ch C 14 13
- 5 Ma A 15 19
- 6 En C 19 15
- 7 Ma B 17 12
对课程 lessons
分组,我们会得到什么呢
- [in]: print(df.groupby(by="lessons"))
- [out]:
- <pandas.core.groupby.generic.DataFrameGroupBy object at 0x00000209C7C76460>
我们看到它实际上还没有进行任何计算,而是返回了一个 DataFrameGroupBy
对象,用 groupby
方法分组后的结果并不能直接查看,而是被存在内存中,输出的时内存地址。
如果要得到我们想要的结果,我们应该怎么做呢? DataFrameGroupBy
对象有很多经过优化的方法:
count
:计算分组中非NA值的数量sum
:计算非NA值的和mean
:计算非NA值的平均值median
:计算非NA值的算术中位数std、var
:无偏(分母为n-1)标准差和方差min、max
:非NA值的最小值和最大值
我们来尝试计算一下各等级的男生人数:
- [in]: group1 = df.groupby(by="grade")
- [in]: print(group1.sum())
- [out]:
- male female
- grade
- A 39 47
- B 43 35
- C 33 28
size()
返回每个分组的元素个数
- [in]: group2 = df.groupby(by="lessons")
- [in]: print(group2.count())
- [in]: print('-' * 50)
- [in]: print(group2.size())
- [out]:
- grade male female
- lessons
- Ch 3 3 3
- En 3 3 3
- Ma 2 2 2
- --------------------------------------------------
- lessons
- Ch 3
- En 3
- Ma 2
- dtype: int64
一次传入多个分组依据,统计各学科各等级的男女生人数
- # 安装学科和成绩进行分组
- [in]: group3 = df.groupby(by=[df["lessons"], df["grade"]])
- [in]: print(group3.sum())
- [out]:
- male female
- lessons grade
- Ch A 14 17
- B 11 11
- C 14 13
- En A 10 11
- B 15 12
- C 19 15
- Ma A 15 19
- B 17 12
我们在分组统计之后如果只想查看男生的情况,当然也是可以的
- [in]: print(df.groupby(by=[df["lessons"], df["grade"]]).sum()["male"])
- [out]:
- lessons grade
- Ch A 14
- B 11
- C 14
- En A 10
- B 15
- C 19
- Ma A 15
- B 17
- Name: male, dtype: int32
这样的写法 df["male"].groupby(by=[df["lessons"], df["grade"]]).sum()
当然也是可以的。
read_csv
data = pd.read_csv("train.csv")
read_table
to_csv
- [in]: df = pd.DataFrame(np.random.randn(4, 5), index=["one", "two", "three", "four"], columns=list("ABCDE"))
- [in]: df.iloc[0, 2] = np.nan
- [in]: df.iloc[[1, 3], 4] = np.nan #锁定五列,将二四行置NaN
- [in]: print(df)
- [out]:
- A B C D E
- one 0.123806 0.493575 NaN 0.476856 0.547563
- two 0.750184 -0.326554 0.448464 0.449652 NaN
- three 1.075840 0.228632 0.769619 -1.091077 0.440128
- four -1.545927 0.243639 1.158786 1.381231 NaN
注:df.mean()是获取每列的均质构成5*1的ndaray
.sort_index()
方法在指定轴上根据索引进行排序,默认为零轴,升序。
.sort_index(axis=0,ascending=True)
axis
: 指定要排序的轴。ascending
: 指递增排序。- [in]: df1 = pd.DataFrame(np.arange(20).reshape(4,5), index = list("cabd"))
- [in]: print(df1)
- [in]: print('-' * 50)
- [out]:
- 0 1 2 3 4
- c 0 1 2 3 4
- a 5 6 7 8 9
- b 10 11 12 13 14
- d 15 16 17 18 19
- --------------------------------------------------
- # 规定按照降序排序
- [in]: print(df1.sort_index(ascending=False))
- [out]:
- 0 1 2 3 4
- d 15 16 17 18 19
- c 0 1 2 3 4
- b 10 11 12 13 14
- a 5 6 7 8 9
.sort_values()
方法在指定轴上根据数值进行排序,默认为零轴,升序
- Series.sort_values(axis=0, ascending=True)
- DataFrame.sort_values(by, axis=0, ascending=True)
by: axis
轴上的某个索引或索引列表。ascending
: 指递增排序。- [in]: df2 = pd.DataFrame(np.arange(20).reshape(4,5), index = list("abcd"))
- [in]: print(df2)
- [out]:
- 0 1 2 3 4
- a 0 1 2 3 4
- b 5 6 7 8 9
- c 10 11 12 13 14
- d 15 16 17 18 19
- # 默认在0轴上,指定对索引为2的那一列按照降序排序
- [in]: print(b.sort_values(2, ascending=False))
- [out]:
- 0 1 2 3 4
- d 15 16 17 18 19
- c 10 11 12 13 14
- b 5 6 7 8 9
- a 0 1 2 3 4
- # 指定在1轴上,对索引为‘c’的那一行进行降序排序
- [in]: print(b.sort_values('a',axis=1, ascending=False))
- [out]:
- 4 3 2 1 0
- a 4 3 2 1 0
- b 9 8 7 6 5
- c 14 13 12 11 10
- d 19 18 17 16 15
适用于 Series
和 DataFrame
类型:
方法 | 说明 |
---|---|
.sum() | 计算数据的总和,按0轴计算,下同 |
.count() | 非Nan值的数量 |
.mean() .median() | 计算数据的算数平均值、算数中位数 |
.var() .std() | 计算数据的方差、标准差 |
.min() .max() | 计算数据的最小值、最大值 |
适用于 Series
类型的方法:
方法 | 说明 |
---|---|
.argmin() .argmax() | 计算数据最大值、最小值所在位置的索引(返回自动索引) |
.idxmin() .idxmax() | 计算数据最大值、最小值所在位置的索引(返回自定义索引) |
适用于 Series
和 DataFrame
类型:
方法 | 说明 |
---|---|
.describe() | 针对0轴(各列)的统计汇总 |
统计 df1 在行方向的均值和列方向的均值
- # 在0轴上的均值
- [in]: print(df1.mean(axis=0))
- [out]:
- 0 7.5
- 1 8.5
- 2 9.5
- 3 10.5
- 4 11.5
- dtype: float64
- # 在1轴上的均值
- [in]: print(df1.mean(axis=1))
- [out]:
- c 2.0
- a 7.0
- b 12.0
- d 17.0
- dtype: float64
适用于 Series
和 DataFrame
类型:
方法 | 说明 |
---|---|
.cumsum() | 依次给出前1、2、…、n个数的和 |
.cumprod() | 依次给出前1、2、…、n个数的积 |
.cummax() | 依次给出前1、2、…、n个数的最大值 |
.cummin() | 依次给出前1、2、…、n个数的最小值 |
- [in]: a = pd.DataFrame(np.arange(20).reshape(4,5), index = list("abcd"))
- [in]: print(a)
- [in]: print("-" * 50)
- [out]:
- 0 1 2 3 4
- a 0 1 2 3 4
- b 5 6 7 8 9
- c 10 11 12 13 14
- d 15 16 17 18 19
- --------------------------------------------------
- [in]: print(a.cumsum())
- [in]: print("-" * 50)
- [out]:
- 0 1 2 3 4
- a 0 1 2 3 4
- b 5 7 9 11 13
- c 15 18 21 24 27
- d 30 34 38 42 46
- --------------------------------------------------
- [in]: print(a.cumprod())
- [in]: print("-" * 50)
- [out]:
- 0 1 2 3 4
- a 0 1 2 3 4
- b 0 6 14 24 36
- c 0 66 168 312 504
- d 0 1056 2856 5616 9576
- --------------------------------------------------
- [in]: print(a.cummax())
- [in]: print("-" * 50)
- [out]:
- 0 1 2 3 4
- a 0 1 2 3 4
- b 5 6 7 8 9
- c 10 11 12 13 14
- d 15 16 17 18 19
- --------------------------------------------------
- [in]: print(a.cummin())
- [out]:
- 0 1 2 3 4
- a 0 1 2 3 4
- b 0 1 2 3 4
- c 0 1 2 3 4
- d 0 1 2 3 4
适用于 Series
和 DataFrame
类型,滚动计算(窗口计算):
方法 | 说明 |
---|---|
.rolling(w).sum() | 依次计算相邻w个元素的和 |
.rolling(w).mean() | 依次计算相邻w个元素的算数平均值 |
.rolling(w).var() | 依次计算相邻w个元素的方差 |
.rolling(w).std() | 依次计算相邻w个元素的标准差 |
.rolling(w).min() .max() | 依次计算相邻w个元素的最小值和最大值 |
- [in]: b = pd.DataFrame(np.arange(20).reshape(4,5), index = list("abcd"))
- [in]: print(b)
- [in]: print("-" * 50)
- [out]:
- 0 1 2 3 4
- a 0 1 2 3 4
- b 5 6 7 8 9
- c 10 11 12 13 14
- d 15 16 17 18 19
- --------------------------------------------------
- # 每一行元素都和他的上一行元素相加。第一行的上一行为NaN,相加还为NaN
- [in]: print(b.rolling(2).sum())
- [in]: print("-" * 50)
- [out]:
- 0 1 2 3 4
- a NaN NaN NaN NaN NaN
- b 5.0 7.0 9.0 11.0 13.0
- c 15.0 17.0 19.0 21.0 23.0
- d 25.0 27.0 29.0 31.0 33.0
- --------------------------------------------------
- [in]: print(b.rolling(3).sum())
- [in]: print("-" * 50)
- [out]:
- 0 1 2 3 4
- a NaN NaN NaN NaN NaN
- b NaN NaN NaN NaN NaN
- c 15.0 18.0 21.0 24.0 27.0
- d 30.0 33.0 36.0 39.0 42.0
什么是相关性呢,现有两个事物,表示为X和Y:
- X增大,Y增大,两个变量正相关
- X增大,Y减小,两个变量负相关
- X增大,Y无视,两个变量不变
在统计学上的度量标准为:协方差
相关分析函数
适用于 Series
和 DataFrame
方法 | 说明 |
---|---|
.cov() | 计算协方差矩阵 |
.corr() | 计算相关系数矩阵,Pearson、Spearman、Kendall等系数 |
我们来看一下效果
- [in]: df = pd.DataFrame(np.random.randn(3,4))
- [in]: print(df)
- [in]: print("-" * 50)
- [in]: print(df.cov())
- [in]: print("-" * 50)
- [in]: print(df.corr())
- [out]:
- 0 1 2 3
- 0 0.040277 -0.301868 0.001866 0.266581
- 1 -0.299964 -0.505190 0.142053 -0.298927
- 2 0.641009 1.433105 1.230602 0.466891
- --------------------------------------------------
- 0 1 2 3
- 0 0.227012 0.489220 0.285790 0.172226
- 1 0.489220 1.134743 0.702208 0.324482
- 2 0.285790 0.702208 0.452397 0.166747
- 3 0.172226 0.324482 0.166747 0.157733
- --------------------------------------------------
- 0 1 2 3
- 0 1.000000 0.963896 0.891789 0.910148
- 1 0.963896 1.000000 0.980070 0.766974
- 2 0.891789 0.980070 1.000000 0.624218
- 3 0.910148 0.766974 0.624218 1.000000
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。