创建pandas对象
使用series来创建pandas对象,实际是创建了一列元素np.NaN表示不是一个数字。
import pandas as pd
import numpy as np
s = pd.Series([1,3,5,np.NaN,8,4])
s
运行结果:
0 1.0
1 3.0
2 5.0
3 NaN
4 8.0
5 4.0
dtype: float64
随机创建以时间为数据元素的数列
dates = pd.date_range('20200924',periods = 6)
dates
运行结果:
DatetimeIndex(['2020-09-24', '2020-09-25', '2020-09-26', '2020-09-27','2020-09-28', '2020-09-29'],
dtype='datetime64[ns]', freq='D')
periods参数表示,这个序列一共有多少时间元素。
DataFrame是一种表格型数据结构,它含有一组有序的列,每列可以是不同的值。DataFrame既有行索引,也有列索引,它可以看作是由Series组成的字典,不过这些Series公用一个索引。
data = pd.DataFrame(np.random.randn(6,4),index = dates, columns = list('ABCD'))
data
运行结果:
A B C D
2020-09-24 0.590682 0.174763 -0.235525 0.548783
2020-09-25 -0.130900 -0.289797 1.986561 0.589900
2020-09-26 -0.937179 0.550399 -2.143900 -0.020046
2020-09-27 0.296671 -1.983746 -1.059754 -0.190418
2020-09-28 -0.455713 -0.311709 -0.537900 -0.857956
2020-09-29 0.631126 -0.891541 -1.800478 0.731037
利用dataframe创建表格型的数据结构,随机产生6行4列的有序数列。并且设置行索引index为dates,列索引为“ABCD”。
通过shape()和values()方法可以将这个表格函数的形状和数组元素输出
data.shape
data.values
运行结果:
(6, 4)
array([[ 0.59068169, 0.17476264, -0.23552531, 0.54878259],
[-0.13089963, -0.28979739, 1.98656097, 0.58989979],
[-0.93717863, 0.55039862, -2.1438998 , -0.02004596],
[ 0.29667129, -1.98374618, -1.0597543 , -0.19041846],
[-0.45571307, -0.31170856, -0.53789977, -0.85795578],
[ 0.63112604, -0.89154051, -1.80047822, 0.73103671]])
由此可以见,dataframe中的数据元素是array对象。
除此之外,我们还可以在pandas中用字典创建数组
d = {'A':1,'B':pd.Timestamp('20200924'),'C':range(4),'D':np.arange(4)}
d
运行结果:
{'A': 1,
'B': Timestamp('2020-09-24 00:00:00'),
'C': range(0, 4),
'D': array([0, 1, 2, 3])}
将上述数组通过dataframe来转变成表格:
df = pd.DataFrame(d)
df
运行结果:
A B C D
0 1 2020-09-24 0 0
1 1 2020-09-24 1 1
2 1 2020-09-24 2 2
3 1 2020-09-24 3 3
第一列为自动生成的数据元素的行号。
查看数据
除了创建pandas对象的方法外,我们经常还需要查看对象的元素数据类型。
df.dtypes
运行结果:
A int64
B datetime64[ns]
C int64
D int64
dtype: object
对应的我们可以看到,刚才我们创建的dataframe数组的各行元素的数据类型。同样的我们也可以每一行每一行的方式去查看对应行的数据类型。
df.A
运行结果:
0 1
1 1
2 1
3 1
Name: A, dtype: int64
当我们查看B列元素数据类型时,发现是datatime类型,但是在pandas中,整一列是series类型。
df.B
type(df.B)
运行结果:
0 2020-09-24
1 2020-09-24
2 2020-09-24
3 2020-09-24
Name: B, dtype: datetime64[ns]
pandas.core.series.Series
在pandas中,还有一些方法可以查看数据中的前几行数据,默认是前5行。同样的,我们也可以查看尾部几行的数据,默认为最后5行数据。
data.head()
data.tail()
在pandas中,除了查看数据以外,通过以下方法,还可以查看行标签、列标签等等。
data.index#表示行标签
data.columns#表示列标签
data.values#表示数组中的值
data.describe()#查看数组整体情况
选择数据
在pandas中,我们可以根据标签进行排序
data.sort_index(axis = 1)
A B C D
2020-09-24 0.590682 0.174763 -0.235525 0.548783
2020-09-25 -0.130900 -0.289797 1.986561 0.589900
2020-09-26 -0.937179 0.550399 -2.143900 -0.020046
2020-09-27 0.296671 -1.983746 -1.059754 -0.190418
2020-09-28 -0.455713 -0.311709 -0.537900 -0.857956
2020-09-29 0.631126 -0.891541 -1.800478 0.731037
也可以根据标签降序排序
data.sort_index(axis = 1,ascending = False)
D C B A
2020-09-24 0.548783 -0.235525 0.174763 0.590682
2020-09-25 0.589900 1.986561 -0.289797 -0.130900
2020-09-26 -0.020046 -2.143900 0.550399 -0.937179
2020-09-27 -0.190418 -1.059754 -1.983746 0.296671
2020-09-28 -0.857956 -0.537900 -0.311709 -0.455713
2020-09-29 0.731037 -1.800478 -0.891541 0.631126
还可以对行标签进行降序排序
data.sort_index(axis = 0,ascending = False)
A B C D
2020-09-29 0.631126 -0.891541 -1.800478 0.731037
2020-09-28 -0.455713 -0.311709 -0.537900 -0.857956
2020-09-27 0.296671 -1.983746 -1.059754 -0.190418
2020-09-26 -0.937179 0.550399 -2.143900 -0.020046
2020-09-25 -0.130900 -0.289797 1.986561 0.589900
2020-09-24 0.590682 0.174763 -0.235525 0.548783
对值进行排序,选中一行/列进行排序
data.sort_values(by = 'A')#默认对选中排序序列进行升序排序
A B C D
2020-09-26 -0.937179 0.550399 -2.143900 -0.020046
2020-09-28 -0.455713 -0.311709 -0.537900 -0.857956
2020-09-25 -0.130900 -0.289797 1.986561 0.589900
2020-09-27 0.296671 -1.983746 -1.059754 -0.190418
2020-09-24 0.590682 0.174763 -0.235525 0.548783
2020-09-29 0.631126 -0.891541 -1.800478 0.731037
选择输出一列数据元素
data['A']
2020-09-24 0.590682
2020-09-25 -0.130900
2020-09-26 -0.937179
2020-09-27 0.296671
2020-09-28 -0.455713
2020-09-29 0.631126
Freq: D, Name: A, dtype: float64
同样也可以选择输出一行数据元素
data[2:4]#输出下标为2的一行数据和下标为3的一行数据(第二个参数4表示到4下标之前,不包括4)
A B C D
2020-09-26 -0.937179 0.550399 -2.143900 -0.020046
2020-09-27 0.296671 -1.983746 -1.059754 -0.190418
但是,这样的选择效率是比较低的,因为每次输出需要查找的元素,计算机还要先判断输入的值为位置参数还是索引参数。效率较高的选择方法是用函数loc和函数iloc。
loc为Selection by Label函数,即为按标签取数据:不需要判断是位置的参数,还是索引标签的参数。
iloc函数为Selection by Position,即按位置选择数据,即第n行,第n列数据,只接受整型参数。
data.loc['20200926':'20200929']
A B C D
2020-09-26 -0.937179 0.550399 -2.143900 -0.020046
2020-09-27 0.296671 -1.983746 -1.059754 -0.190418
2020-09-28 -0.455713 -0.311709 -0.537900 -0.857956
2020-09-29 0.631126 -0.891541 -1.800478 0.731037
data.iloc[2:4]#通过位置标签进行索引,选择行;2:4为左闭右开区间,即取2,3
A B C D
2020-09-26 -0.937179 0.550399 -2.143900 -0.020046
2020-09-27 0.296671 -1.983746 -1.059754 -0.190418
data.loc[:,['B','C']]#只选中B,C中的数据
B C
2020-09-24 0.174763 -0.235525
2020-09-25 -0.289797 1.986561
2020-09-26 0.550399 -2.143900
2020-09-27 -1.983746 -1.059754
2020-09-28 -0.311709 -0.537900
2020-09-29 -0.891541 -1.800478
若是要指定dataframe中的某几行某几列,就需要在参数中详细指出对应的行标签和列标签。
data.loc['20200925':'20200927',['B','C']]
B C
2020-09-25 -0.289797 1.986561
2020-09-26 0.550399 -2.143900
2020-09-27 -1.983746 -1.059754
当然,在pandas中还有很多选择数据的方式
#使用loc函数选择数据元素
start = time.clock()
data.loc['20200925','B']
end = (time.clock() - start)
end
运行结果:
0.0008910000000001972
#使用pandas中Timestamp函数选择数据元素
start = time.clock()
data.at[pd.Timestamp('20200925'),'B']
end = (time.clock() - start)
end
运行结果:
0.0007549999999998391
比较上述两种方式,我们发现,方法2的效率明显高于方法1。虽然选择数据的方式有很多,但是有的效率高有的效率低,需要结合实际情况选择适合的方法。
iloc函数还可以对数据进行通过位置的访问:
data.iloc[1]#访问第一列数据
运行结果:
A -0.130900
B -0.289797
C 1.986561
D 0.589900
Name: 2020-09-25 00:00:00, dtype: float64
data.iloc[1:3]#访问两行数据
运行结果:
A B C D
2020-09-25 -0.130900 -0.289797 1.986561 0.589900
2020-09-26 -0.937179 0.550399 -2.143900 -0.020046
data.iloc[1:3,2:4]#第一组参数决定查找的行,第二组参数决定查找的列
运行结果:
C D
2020-09-25 1.986561 0.589900
2020-09-26 -2.143900 -0.020046
data.iloc[:,1:3]#默认访问全部行的1,2列
运行结果:
B C
2020-09-24 0.174763 -0.235525
2020-09-25 -0.289797 1.986561
2020-09-26 0.550399 -2.143900
2020-09-27 -1.983746 -1.059754
2020-09-28 -0.311709 -0.537900
2020-09-29 -0.891541 -1.800478
在pandas中可以访问特定数据元素:
data.iloc[1,1]
%timeit df.iloc[1,1]#测试运行的时间
运行结果:
7.75 µs ± 34 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
data.iat[1,1]
%timeit df.iat[1,1]
运行结果:
5.24 µs ± 63.4 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
综上比较,发现iat函数相比iloc函数更适合用于访问特定的元素位置。
我们可以单独查找对应行列数据,也可以指定对应位置的数据,还可以设置一些限制,查询出满足这些限制的数据。
#以数据的A列作为筛选对象,找到A中大于0的数据的每一行
data[data.A > 0]
运行结果:
A B C D
2020-09-24 0.590682 0.174763 -0.235525 0.548783
2020-09-27 0.296671 -1.983746 -1.059754 -0.190418
2020-09-29 0.631126 -0.891541 -1.800478 0.731037
#对dataframe中的所有数据设置筛选条件是需要大于0的数据
data[data > 0]
运行结果:
A B C D
2020-09-24 0.590682 0.174763 NaN 0.548783
2020-09-25 NaN NaN 1.986561 0.589900
2020-09-26 NaN 0.550399 NaN NaN
2020-09-27 0.296671 NaN NaN NaN
2020-09-28 NaN NaN NaN NaN
2020-09-29 0.631126 NaN NaN 0.731037
根据运行结果,我们可知,在整个dataframe中,只输出了data值大于0的数据,小于0的数据用NaN表示。
过滤数据,我们还可以通过设置tag的方式,首先给每一行数据都添加tag:
data2 = data.copy()
tag = ['a']*2+['b']*2+['c']*2
data2['TAG'] = tag
data2
运行结果:
A B C D TAG
2020-09-24 0.590682 0.174763 -0.235525 0.548783 a
2020-09-25 -0.130900 -0.289797 1.986561 0.589900 a
2020-09-26 -0.937179 0.550399 -2.143900 -0.020046 b
2020-09-27 0.296671 -1.983746 -1.059754 -0.190418 b
2020-09-28 -0.455713 -0.311709 -0.537900 -0.857956 c
2020-09-29 0.631126 -0.891541 -1.800478 0.731037 c
当dataframe有自己的tag以后,我们就可以通过tag来进行数据过滤:
data2[data2.TAG.isin(['a','c'])]
运行结果:
A B C D TAG
2020-09-24 0.590682 0.174763 -0.235525 0.548783 a
2020-09-25 -0.130900 -0.289797 1.986561 0.589900 a
2020-09-28 -0.455713 -0.311709 -0.537900 -0.857956 c
2020-09-29 0.631126 -0.891541 -1.800478 0.731037 c
pandas中修改dataframe中的元素:
data.iat[0,0] = 100#将dataframe中的第一个元素的值修改了
运行结果:
A B C D
2020-09-24 100.000000 0.174763 -0.235525 0.548783
2020-09-25 -0.130900 -0.289797 1.986561 0.589900
2020-09-26 -0.937179 0.550399 -2.143900 -0.020046
2020-09-27 0.296671 -1.983746 -1.059754 -0.190418
2020-09-28 -0.455713 -0.311709 -0.537900 -0.857956
2020-09-29 0.631126 -0.891541 -1.800478 0.731037
data.A = range(6)#将数据表中的第A列元素修改为0-5的序列
运行结果:
A B C D
2020-09-24 0 0.174763 -0.235525 0.548783
2020-09-25 1 -0.289797 1.986561 0.589900
2020-09-26 2 0.550399 -2.143900 -0.020046
2020-09-27 3 -1.983746 -1.059754 -0.190418
2020-09-28 4 -0.311709 -0.537900 -0.857956
2020-09-29 5 -0.891541 -1.800478 0.731037
data.B = 200#将数据表中的B列元素修改为一个标量
运行结果:
A B C D
2020-09-24 0 200 -0.235525 0.548783
2020-09-25 1 200 1.986561 0.589900
2020-09-26 2 200 -2.143900 -0.020046
2020-09-27 3 200 -1.059754 -0.190418
2020-09-28 4 200 -0.537900 -0.857956
2020-09-29 5 200 -1.800478 0.731037
如果是要将一整个列表的数据都修改为标量,需要shape相匹配。标量可以对整个子表进行复制,传一个行列和数组相等的子表,就可以直接进行修改。
data.iloc[:,2:4] = 1000
运行结果:
A B C D
2020-09-24 0 200 1000 1000
2020-09-25 1 200 1000 1000
2020-09-26 2 200 1000 1000
2020-09-27 3 200 1000 1000
2020-09-28 4 200 1000 1000
2020-09-29 5 200 1000 1000
处理丢失数据
首先导包
%matplotlib inline
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
创建序列和数据集,通过日期来索引
dates = pd.date_range('20200926',periods = 6)
df = pd.DataFrame(np.random.randn(6,4),index = dates,columns = list('ABCD'))
df
运行结果:
A B C D
2020-09-26 0.676611 -0.350692 -1.888116 -0.437411
2020-09-27 -0.200051 0.515761 -0.466309 -0.479626
2020-09-28 0.694556 -0.678058 -0.650581 0.426779
2020-09-29 -0.099156 -1.544060 0.792024 0.622751
2020-09-30 -0.180553 -0.714780 -0.914556 -0.189826
2020-10-01 0.924494 -0.722958 -0.610121 1.105818
制造数据缺失项
df1 = df.reindex(index = dates[0:4],columns = list(df.columns)+['E'])
#reindex的参数index是指行索引为日期,一共有4个;列索引是原dataframe的列索引基础上再增加一个E作为新的列索引
df1
运行结果:
A B C D E
2020-09-26 0.676611 -0.350692 -1.888116 -0.437411 NaN
2020-09-27 -0.200051 0.515761 -0.466309 -0.479626 NaN
2020-09-28 0.694556 -0.678058 -0.650581 0.426779 NaN
2020-09-29 -0.099156 -1.544060 0.792024 0.622751 NaN
得到一列新的,有数据缺失的列
给新插入的列进行部分赋值
df1.loc[dates[1:3],'E'] = 2
df1
运行结果:
A B C D E
2020-09-26 0.676611 -0.350692 -1.888116 -0.437411 NaN
2020-09-27 -0.200051 0.515761 -0.466309 -0.479626 2.0
2020-09-28 0.694556 -0.678058 -0.650581 0.426779 2.0
2020-09-29 -0.099156 -1.544060 0.792024 0.622751 NaN
处理数据1:将最后一列为空的数据丢掉
df1.dropna()
运行结果:
A B C D E
2020-09-27 -0.200051 0.515761 -0.466309 -0.479626 2.0
2020-09-28 0.694556 -0.678058 -0.650581 0.426779 2.0
这样就完成了一个简单的处理数据丢失序列的操作。
处理数据2:用fillna函数将空数据用默认值来替换。
DataFrame.fillna(self, value=None, method=None, axis=None, inplace=False, limit=None, downcast=None, **kwargs)
使用指定的方法填充NA/NaN值。
#数据处理2:用fillna函数将空数据用默认值来替换
df1.fillna(value = 5)
运行结果:
A B C D E
2020-09-26 0.676611 -0.350692 -1.888116 -0.437411 5.0
2020-09-27 -0.200051 0.515761 -0.466309 -0.479626 2.0
2020-09-28 0.694556 -0.678058 -0.650581 0.426779 2.0
2020-09-29 -0.099156 -1.544060 0.792024 0.622751 5.0
在上述对缺失数据序列的操作中,不管是dropna还是fillna,其返回值都是复制的,没有修改本身数据。
处理数据3:判断数据集是否包含空数据。
pd.isnull(df1)
A B C D E
2020-09-26 False False False False True
2020-09-27 False False False False False
2020-09-28 False False False False False
2020-09-29 False False False False True
当表格特别大的时候,可以使用any()来找出带有空数据的列;再加一个any()可以对数据集是否包含空数据的判断进一步进行简化。
pd.isnull(df1).any()
运行结果:
A False
B False
C False
D False
E True
dtype: bool
pd.isnull(df1).any().any()
运行结果:True
数据运算
在pandas中,空数据是不参与计算的.
对df求平均值:
df1.mean()#默认是按列求平均值
运行结果:
A 0.267990
B -0.514262
C -0.553246
D 0.033123
E 2.000000
dtype: float64
#按行求平均值
df1.mean(aixs = 1)
求累加值,空值是不参与计算的:
df1.cumsum()#默认按行向下累加?
运行结果:
A B C D E
2020-09-26 0.676611 -0.350692 -1.888116 -0.437411 NaN
2020-09-27 0.476560 0.165069 -2.354424 -0.917037 2.0
2020-09-28 1.171116 -0.512989 -3.005006 -0.490258 4.0
2020-09-29 1.071960 -2.057049 -2.212982 0.132493 NaN
pandas广播的概念:广播运算是指两个数组进行运算,一个是Series数组(即一维数组),另一个是DataFrame数组(多维数组)。一维数组看成是一行,分别与多维数组的每一行进行运算。需要注意的是,如果一维数组过短,结果每行的长度以最大值为准,超过的部分空值,即NaN。
#
s = pd.Series([1,3,5,np.nan,6,8],index = dates).shift(2)
运行结果:
2020-09-26 NaN
2020-09-27 NaN
2020-09-28 1.0
2020-09-29 3.0
2020-09-30 5.0
2020-10-01 NaN
Freq: D, dtype: float64
不同维度,广播运算默认在1轴。
dataframe的减法:用df-s,每一列都减一次s,相当于对s进行横向扩展.这里用行标签作为关键字的索引。
df.sub(s,axis = 'index')
运行结果:
A B C D
2020-09-26 NaN NaN NaN NaN
2020-09-27 NaN NaN NaN NaN
2020-09-28 -0.305444 -1.678058 -1.650581 -0.573221
2020-09-29 -3.099156 -4.544060 -2.207976 -2.377249
2020-09-30 -5.180553 -5.714780 -5.914556 -5.189826
2020-10-01 NaN NaN NaN NaN
累加函数-apply会将列的参数传给累加函数
df.apply(np.cumsum)
运行结果:
A B C D
2020-09-26 0.676611 -0.350692 -1.888116 -0.437411
2020-09-27 0.476560 0.165069 -2.354424 -0.917037
2020-09-28 1.171116 -0.512989 -3.005006 -0.490258
2020-09-29 1.071960 -2.057049 -2.212982 0.132493
2020-09-30 0.891407 -2.771829 -3.127538 -0.057332
2020-10-01 1.815901 -3.494787 -3.737659 1.048486
按照列从上到下累加。
每一列的最大值减去每一列的最小值:
df.apply(lambda x : x.max() - x.min())
数据合并
s = pd.Series(np.random.randint(10,20,size = 20))#创建一个在10-20区间的series对象,大小为20个
#查看每一个数据产生了几次
s.value_counts()
#查看产生最多的数字是几
s.mode()
数据合并操作
首先构造一个dataframe对象,随机生成其中的数据元素。
#数据合并
df = pd.DataFrame(np.random.randn(10,4),columns = list('ABCD'))
运行结果:
A B C D
0 1.289920 -0.960535 0.491643 -1.406865
1 -0.162930 -0.270254 0.931813 -1.778384
2 -2.571621 0.269298 2.068740 -0.856628
3 -0.833157 -0.318298 -0.621249 0.068925
4 0.169541 1.820101 -0.331222 -0.504535
5 -0.149618 -0.055813 -0.730151 0.874737
6 1.109053 -0.049291 0.305303 0.231087
7 -0.699549 -0.117372 0.320132 -1.211569
8 0.125819 -1.407581 -0.629429 -1.144377
9 -0.027972 -0.591627 -0.096483 -0.078706
#取前三个数据
df.iloc[:3]
#取中间位置的数据
df.iloc[3:7]
#取后面三个数据
df.iloc[7:]
#合并以上三个部分的数据
df1 = pd.concat([df.iloc[:3],df.iloc[3:7],df.iloc[7:]])
df1
#验证是否是相等的数据集
df == df1
#简单表示的验证方法
(df == df1).all().all()
上述操作就是对数据的合并
pandas联合方式
- pandas.merge 根据一个或多个键将行进行连接,与SQL数据库的1连接操作类似
- pandas.concat 使对象在轴向上进行黏合或 ‘堆叠’
- join()方法将不再解释
- combine_first()实例方法允许将重叠的数据拼接在一起,以使用一个对象的值填充另个对象的缺失值
#创建两个dataframe对象
left = pd.DataFrame({'key':['foo','foo'],'lval':[1,2]})
right = pd.DataFrame({'key':['foo','foo'],'rval':[4,5]})
# select *from left inner join right on left.key = right.key
#通过两个dataframe中相同的标签,将两个dataframe对象合并
pd.merge(left,right,on = 'key')
运行结果:
key lval rval
0 foo 1 4
1 foo 1 5
2 foo 2 4
3 foo 2 5
插入数据操作
#创建一个序列,作为待插入数据
s = pd.Series(np.random.randint(1,5,size = 4),index = list('ABCD'))
#插入数据
df.append(s,ignore_index = True)
运行结果:
A B C D
0 1.289920 -0.960535 0.491643 -1.406865
1 -0.162930 -0.270254 0.931813 -1.778384
2 -2.571621 0.269298 2.068740 -0.856628
3 -0.833157 -0.318298 -0.621249 0.068925
4 0.169541 1.820101 -0.331222 -0.504535
5 -0.149618 -0.055813 -0.730151 0.874737
6 1.109053 -0.049291 0.305303 0.231087
7 -0.699549 -0.117372 0.320132 -1.211569
8 0.125819 -1.407581 -0.629429 -1.144377
9 -0.027972 -0.591627 -0.096483 -0.078706
10 2.000000 1.000000 3.000000 1.000000
插入了数据后,再输出df,数据没有发生变化,说明append返回的是copy。
数据分组
#创建一个dataframe对象
df = pd.DataFrame({'A':['foo','bar','foo','bar',
'foo','bar','foo','foo'],
'B':['one','one','two','three',
'two','two','one','three'],
'C':np.random.randn(8),
'D':np.random.randn(8)})
#根据a中的元素进行分组,再求和
df.groupby('A').sum()
运行结果:
C D
A
bar 1.864006 -0.131504
foo 1.046744 2.534421
分组的步骤
在进行分组时,数据按照一定的规则进行分组,按照分组进行一定的计算。也可以进行多个分组,先通过a来分成两个大组,再通过b来分成小组。
#先按照a分大组,再在a中按照b来分小组
df.groupby(['A','B']).sum()
运行结果:
C D
A B
bar one 0.890682 0.728664
three 1.205480 -2.440707
two -0.232157 1.580539
foo one 0.309238 2.513686
three 2.747612 0.876861
two -2.010106 -0.856126
#先按照b分大组,再在b中按照a来分小组
df.groupby(['B','A']).sum()
运行结果:
C D
B A
one bar 0.890682 0.728664
foo 0.309238 2.513686
three bar 1.205480 -2.440707
foo 2.747612 0.876861
two bar -0.232157 1.580539
foo -2.010106 -0.856126
数据整型
#设置为inline风格
%matplotlib inline
#导包
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
#创建元组列表,作为行索引
tuples = list(zip(*[['bar','bar','baz','baz',
'foo','foo','qux','qux'],
['one','two','one','two',
'one','two','one','two']]))
运行结果:
[('bar', 'one'),
('bar', 'two'),
('baz', 'one'),
('baz', 'two'),
('foo', 'one'),
('foo', 'two'),
('qux', 'one'),
('qux', 'two')]
#怎么创建索引
#1.因为是双层索引,因此可以给它们命名
index = pd.MultiIndex.from_tuples(tuples,names=['first','second'])
运行结果:
MultiIndex([('bar', 'one'),
('bar', 'two'),
('baz', 'one'),
('baz', 'two'),
('foo', 'one'),
('foo', 'two'),
('qux', 'one'),
('qux', 'two')],
names=['first', 'second'])
#2.创建数组
df = pd.DataFrame(np.random.randn(8,2),index = index,columns = ['A','B'])
运行结果:
A B
first second
bar one 1.588584 0.163825
two 1.192467 1.301092
baz one 0.369533 -0.996044
two 0.601226 -0.063069
foo one -0.059276 -0.286547
two -0.873837 0.791236
qux one 0.544028 -0.731203
two 0.367554 0.042145
查看索引
stacked.index
将索引转换回原形
stacked.unstack()
再次转换后的数据表示
stacked.unstack().unstack()
运行结果:
A B
second one two one two
first
bar 1.588584 1.192467 0.163825 1.301092
baz 0.369533 0.601226 -0.996044 -0.063069
foo -0.059276 -0.873837 -0.286547 0.791236
qux 0.544028 0.367554 -0.731203 0.042145
数据透视
#创建一个dataframe对象,索引就是前面的编号
df = pd.DataFrame({'A':['one','one','two','three']*3,
'B':['A','B','C']*4,
'C':['foo','foo','foo','bar','bar','bar']*2,
'D':np.random.randn(12),
'E':np.random.randn(12)})
#注意:在创建datdaframe时,每一行列的元素应该时相同的
#以a、b为行索引,c为列索引的数据
df.pivot_table(values = ['D'],index = ['A','B'],columns = ['C'])
#a为行索引,c为列索引,查看e的值
df.pivot_table(values = ['E'],index = ['A'],columns = ['C'])
这个数据集的列索引就是abcde,abc是一些字符串的数据。数据透视就是看其中一部分数据。如果生成数据透视表时,出现NAn说明数据在原始数据集中不存在。
如何算出来这个数据索引
#1.首先找到a == one的数据集
df[df.A == 'one']
运行结果:
A B C D E
0 one A foo -0.474027 0.505072
1 one B foo 0.587796 0.714229
4 one B bar -0.339971 -0.641512
5 one C bar -0.414495 -0.137854
8 one C foo 2.024576 1.250698
9 one A bar -1.519039 0.191107
#2.以c作为列标签分组,然后求平均值
df[df.A == 'one'].groupby('C').mean()
运行结果:
D E
C
bar -0.757835 -0.196086
foo 0.712782 0.823333
数据透视表有多个的时候,会取平均值。数据透视表中对应没有值的时候,就用NAN表示。
时间序列
在pandas中,有提供了强大时间序列处理函数。
#1.首先创建一个时间序列
rng = pd.date_range('20200927',periods = 600,freq = 's')
#第一个参数是起始时间,第二个参数是创建多少个,第三个参数是单位(时间)
运行结果:
DatetimeIndex(['2020-09-27 00:00:00', '2020-09-27 00:00:01',
'2020-09-27 00:00:02', '2020-09-27 00:00:03',
'2020-09-27 00:00:04', '2020-09-27 00:00:05',
'2020-09-27 00:00:06', '2020-09-27 00:00:07',
'2020-09-27 00:00:08', '2020-09-27 00:00:09',
...
'2020-09-27 00:09:50', '2020-09-27 00:09:51',
'2020-09-27 00:09:52', '2020-09-27 00:09:53',
'2020-09-27 00:09:54', '2020-09-27 00:09:55',
'2020-09-27 00:09:56', '2020-09-27 00:09:57',
'2020-09-27 00:09:58', '2020-09-27 00:09:59'],
dtype='datetime64[ns]', length=600, freq='S')
#创建一个值,与之对应
#创建0-500随机数,总共创建时间序列长度那么多数据,设置索引
s = pd.Series(np.random.randint(0,500,len(rng)),index = rng)
运行结果:
2020-09-27 00:00:00 182
2020-09-27 00:00:01 362
2020-09-27 00:00:02 252
2020-09-27 00:00:03 345
2020-09-27 00:00:04 388
...
2020-09-27 00:09:55 406
2020-09-27 00:09:56 496
2020-09-27 00:09:57 0
2020-09-27 00:09:58 28
2020-09-27 00:09:59 280
Freq: S, Length: 600, dtype: int64
#就像股票的实时交易数据一样,每一秒都有一个交易量
#需要对数据进行重新采样,参数1设置采样时间,参数2设置采样的方法
s.resample('2Min').median()
#how这个关键词resample中已经不适用,改为.median()
运行结果:
2020-09-27 00:00:00 256.5
2020-09-27 00:02:00 272.5
2020-09-27 00:04:00 245.5
2020-09-27 00:06:00 269.5
2020-09-27 00:08:00 230.0
Freq: 2T, dtype: float64
创建了时间序列,可以做加法和减法
#创建时间序列
rng = pd.period_range('2000Q1','2020Q1',freq = 'Q')
rng
PeriodIndex(['2000Q1', '2000Q2', '2000Q3', '2000Q4', '2001Q1', '2001Q2',
'2001Q3', '2001Q4', '2002Q1', '2002Q2', '2002Q3', '2002Q4',
'2003Q1', '2003Q2', '2003Q3', '2003Q4', '2004Q1', '2004Q2',
'2004Q3', '2004Q4', '2005Q1', '2005Q2', '2005Q3', '2005Q4',
'2006Q1', '2006Q2', '2006Q3', '2006Q4', '2007Q1', '2007Q2',
'2007Q3', '2007Q4', '2008Q1', '2008Q2', '2008Q3', '2008Q4',
'2009Q1', '2009Q2', '2009Q3', '2009Q4', '2010Q1', '2010Q2',
'2010Q3', '2010Q4', '2011Q1', '2011Q2', '2011Q3', '2011Q4',
'2012Q1', '2012Q2', '2012Q3', '2012Q4', '2013Q1', '2013Q2',
'2013Q3', '2013Q4', '2014Q1', '2014Q2', '2014Q3', '2014Q4',
'2015Q1', '2015Q2', '2015Q3', '2015Q4', '2016Q1', '2016Q2',
'2016Q3', '2016Q4', '2017Q1', '2017Q2', '2017Q3', '2017Q4',
'2018Q1', '2018Q2', '2018Q3', '2018Q4', '2019Q1', '2019Q2',
'2019Q3', '2019Q4', '2020Q1'],
dtype='period[Q-DEC]', freq='Q-DEC')
rng.to_timestamp()#将时间序列的数据类型转换成日期形式
#可以做减法
pd.Timestamp('20160301')-pd.Timestamp('20160201')#两个日期之间的时间差
#可以做加法
pd.Timestamp('20160301')+pd.Timedelta(days=5)#从0301开始往后的第5天,精确到秒
数据可视化
category数据类型
Categoricals 是 pandas 的一种数据类型,对应着被统计的变量。Categoricals 是由固定的且有限数量的变量组成的。比如:性别、社会阶层、血型、国籍、观察时段、赞美程度等等。
与其它被统计的变量相比,categorical 类型的数据可以具有特定的顺序——比如:按程度来设定,“强烈同意”与“同意”,“首次观察”与“二次观察”,但是不能做按数值来进行排序操作(比如:sort_by 之类的,换句话说,categorical 的顺序是创建时手工设定的,是静态的)
类型数据的每一个元素的值要么是预设好的类型中的某一个,要么是空值(np.nan)。顺序是由预设好的类型集合来决定的,而不是按照类型集合中各个元素的字母顺序排序的。categorical 实例的内部是由类型名字集合和一个整数组成的数组构成的,后者标明了类型集合真正的值。
(参考:category的应用)
#categrory数据类型
df = pd.DataFrame({"id":[1,2,3,4,5,6],"raw_grade":['a','b','b','a','a','d']}
运行结果:
id raw_grade
0 1 a
1 2 b
2 3 b
3 4 a
4 5 a
5 6 d
#创建category数据
df ['grade'] = df.raw_grade.astype('category')
id raw_grade grade
0 1 a a
1 2 b b
2 3 b b
3 4 a a
4 5 a a
5 6 d d
#通过函数输出元素类别
df.grade.cat.categories = ['very good','good','bad']
id raw_grade grade
0 1 a very good
1 2 b good
2 3 b good
3 4 a very good
4 5 a very good
5 6 d bad
#按照值来排序,而不是按照命名来排序
df.sort_values(by = 'grade',ascending = True)
id raw_grade grade
0 1 a very good
3 4 a very good
4 5 a very good
1 2 b good
2 3 b good
5 6 d bad
可视化数据
#创建数据
s = pd.Series(np.random.randn(1000),index = pd.date_range('20200101',periods = 1000))
#对数据求和
s = s.cumsum()
#把数据画出来
s.plot()
运行结果:
数据载入与保存
pandas数据读写
pandas很方便将数据保存到磁盘,也很方便到磁盘去读取数据。
#创建数据
df = pd.DataFrame(np.random.randn(100,4),columns = list('ABCD'))
#写入磁盘
df.to_csv('data.csv')
#查看磁盘中的数据文件
%ls
#查看数据名
%more data.csv
#读数据
pd.read_csv('data.csv')
#read读回存入磁盘的数据(可能出现异常,写入磁盘时的索引值被作为数据存入)
#选择对应的数据列作为索引,避免将索引作为数据值的情况
pd.read_csv('data.csv',index_col = 0)