023 pandas基础入门操作

创建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)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值