数据处理进阶知识
- 按组分类后统计频数
先用groupby()函数分组,然后带count()函数,即可求出该组的频数值,比如:
In [1]:
import pandas as pd
df=pd.DataFrame({'num':['one','two','three','one'],'values':['2','3','2','5']})
df.groupby('num').count()
Out[1]:
values
num
one 2
three 1
two 1
也可以直接对某列进行value_counts():
In [2]:
import pandas as pd
df=pd.DataFrame({'num':['one','two','three','one'],'values':['2','3','2','5']})
print df.num.value_counts()
print '*'*30
#或者写成df['num'].value_counts()也行
print df['num'].value_counts()
one 2
three 1
two 1
Name: num, dtype: int64
******************************
one 2
three 1
two 1
Name: num, dtype: int64
2.获得累计求和值
累计求和英文是cumulative sum, 只需在计算频数后加上.cumsum()
,即可得出答案:
In [3]:
import pandas as pd
df=pd.DataFrame({'num':['one','two','three','one'],'values':['2','3','2','5']})
print df.num.value_counts()
print '*'*30
#或者写成df['num'].value_counts()
print df['num'].value_counts().cumsum()
one 2
three 1
two 1
Name: num, dtype: int64
******************************
one 2
three 3
two 4
Name: num, dtype: int64
3.数据透视表
创建透视表的格式是df.pivot_table(index='',columns='',values='',aggfunc=)
In [4]:
import pandas as pd
df=pd.DataFrame({'num':['one','two','three','one'],'values':[2,3,2,5]})
df['cat']=['little cat','fat cat','little cat','my cat']
df['cat label']=[20,38,27,56]
print df
print "*"*30
print df.pivot_table(index='cat') #以cat列为索引,并尝试找出具有相同值的行的规律,默认是找平均数
num values cat cat label
0 one 2 little cat 20
1 two 3 fat cat 38
2 three 2 little cat 27
3 one 5 my cat 56
******************************
cat label values
cat
fat cat 38.0 3
little cat 23.5 2
my cat 56.0 5
除了求平均值,我们还可以通过定义aggfunc来实现不同的目的,比如计算频数:
In[5]:
print df
print "*"*30
print df.pivot_table(index='cat',aggfunc='count')
num values cat cat label
0 one 2 little cat 20
1 two 3 fat cat 38
2 three 2 little cat 27
3 one 5 my cat 56
******************************
cat label num values
cat
fat cat 1 1 1
little cat 2 2 2
my cat 1 1 1
实际运用中,数据表往往有很多列,我们若只想显示某一列,则可用values参数来进行定义:
In[6]:
print df
print "*"*30
df.pivot_table(index='cat',aggfunc=len,values='num')
#len表示计数
#以cat列为索引,并找出num列的计数值
num values cat cat label
0 one 2 little cat 20
1 two 3 fat cat 38
2 three 2 little cat 27
3 one 5 my cat 56
******************************
Out[33]:
cat
fat cat 1
little cat 2
my cat 1
Name: num, dtype: int64
在透视表函数中,参数还可指定多列:
In[7]:
print df
print "*"*30
df.pivot_table(index='cat',aggfunc=[np.mean,len],values=['num','cat label'])
#len表示计数
#以cat列为索引,并找出num列的计数值
num values cat cat label
0 one 2 little cat 20
1 two 3 fat cat 38
2 three 2 little cat 27
3 one 5 my cat 56
******************************
Out[7]:
In[8]:
index也可以有多个,按顺序进行分组计数:
print df
print "*"*30
df.pivot_table(index=['cat','num'],aggfunc=[np.mean,len],values=['num','cat label'])
#len表示计数
#以cat列为索引,然后再以num为索引,对每一行的数据先求均值再求长度
num values cat cat label
0 one 2 little cat 20
1 two 3 fat cat 38
2 three 2 little cat 27
3 one 5 my cat 56
Out[8]:
两个索引同时看有点不好看,那么可以同时制定索引和列名,换种方式呈现结果:
In[9]:
print df
print "*"*30
df.pivot_table(index=['cat'],columns=['num'],aggfunc=[np.mean],values=['num','cat label'])
#len表示计数
#以cat列为索引,以num的values为打横的列名,然后计算相对应的mean值
#若没结果,则填入空值
num values cat cat label
0 one 2 little cat 20
1 two 3 fat cat 38
2 three 2 little cat 27
3 one 5 my cat 56
******************************
若需对空值进行填充,则可加上fill_value
参数,比如
df.pivot_table(index=['cat'],columns=['num'],aggfunc=[np.mean],values=['num','cat label'],fill_value='0')
#将空值替换成数字0
再进一步,求每列数值占当列数值总额的百分比:
In [10]:
print df1
df1.apply(lambda x:(x/x.sum())*100) #默认按列求和
#如果要按行相处,则加入axis=1即可
#df1.apply(lambda x:(x/x.sum())*100,axis='columns')
#计算每个值占当列的百分比
mean
values cat label
num one three two one three two
cat
fat cat 0 0 3 0 0 38
little cat 2 2 0 20 27 0
my cat 5 0 0 56 0 0
Out[10]:
若要在df下面新增一行来显示结果,则可以用df.loc['your cat']=
来实现:
In [11]:
print df1
df1.loc['sum']=df1.apply(lambda x:x.sum()) #新增一行显示计算结果
df1
values cat label
num
one 2 20
two 3 38
three 2 27
one 5 56
Out[11]:
values cat label
num
one 2 20
two 3 38
three 2 27
one 5 56
sum 12 141
- index的相关处理
set_index()后,如果想返回初始的状态,则可用reset_index(),如果本身就是初始状态,用了reset_index()后,会多了一个index_0作为列。
若是set_index后,不想显示index的名字而导致多了一个空白行,则可用'df.index.name=None'来使其消失。
还可以用reindex()函数,对数据集的索引进行重新编制,用其他数据集的索引,用原数据集的数据,一一配对,没有数据的地方以空值填充:
In [12]:
df_index=pd.date_range('10/10/2017',periods=5,freq='D')
df1=pd.DataFrame({'cash':[100,30,np.nan,32,199]},index=df_index)
print df1
df_index1=pd.date_range('10/10/2017',periods=8,freq='2D')
df1.reindex(df_index1)
cash
2017-10-10 100
2017-10-11 30
2017-10-12 NaN
2017-10-13 32
2017-10-14 199
Out[12]:
cash
2017-10-10 100
2017-10-12 NaN
2017-10-14 199
2017-10-16 NaN
2017-10-18 NaN
2017-10-20 NaN
2017-10-22 NaN
2017-10-24 NaN
- 设定数据集的布局
先创建一个df:
In [13]:
df=pd.DataFrame(np.arange(0,12).reshape((3,4)),index=['1','2','3'],columns=['a','b','c','d'])
print df
df1=pd.melt(df,id_vars=['b']) #对df数据集按变量b重新布局,显示出当变量b为某个值时,其他变量对应的values是什么
#改变布局后,只显示两列数据
df1
a b c d
1 0 1 2 3
2 4 5 6 7
3 8 9 10 11
Out[13]:
实际运用中,可设id_vars=交易日期,然后就得出两列数据,股票代码和收盘价。
In [14]:
df1=pd.melt(df,id_vars=['b'],value_vars=['c'])
df1
Out[14]:
b variable value
0 1 c 2
1 5 c 6
2 9 c 10
变回去也行,用pivot_table()即可:
In [14]:
df1=pd.melt(df,id_vars=['a'])
print df1
df1.pivot_table(index='a',columns='variable',values='value') #pivot_table是melt的反面
a variable value
0 0 b 1
1 4 b 5
2 8 b 9
3 0 c 2
4 4 c 6
5 8 c 10
6 0 d 3
7 4 d 7
8 8 d 11
Out[14]:
variable b c d
a
0 1 2 3
4 5 6 7
8 9 10 11
要把这个a消掉,加个reset_index()即可。
- 类别设置
以学生考试成绩打分为例,将不同分值的结果赋予定性的判断:
In [15]:
import pandas as pd
import numpy as np
df=pd.DataFrame({'student':['one','two','three','four'],'marks':[55,79,73,62],'raw_grade':['c','a','a','b']})
df['grade']=df['raw_grade'].astype('category') #新增一列,内容是marks的values,但类别为分类
df.set_index('student')
print df['grade']
df['grade'].cat.categories=['good','just so so','bad'] #分别对应a\b\c, cat是category的意思
df['grade']
0 c
1 a
2 a
3 b
Name: grade, dtype: category
Categories (3, object): [a, b, c]
Out[15]:
0 bad
1 good
2 good
3 just so so
Name: grade, dtype: category
Categories (3, object): [good, just so so, bad]
- 链接两个df
假如有两个df表,他们某个列有相同的values,则可以进行合并,进行对应填充:
In [16]:
import pandas as pd
import numpy as np
df1=pd.DataFrame({'animal':['dog','cat','cat','cow','dog'],'price':[55,79,73,62,40],'grade':['c','a','c','b','d']})
df2=pd.DataFrame({'animals':['dog','cat','cow'],'weight':[553,792,731]})
print df1
print df2
df=pd.merge(df1,df2,how='inner',left_on='animal',right_on='animals') #方式用内部合并,左边显示animal的数据,右边显示animals的数据,对应填充。
df
animal grade price
0 dog c 55
1 cat a 79
2 cat c 73
3 cow b 62
4 dog d 40
animals weight
0 dog 553
1 cat 792
2 cow 731
Out[16]:
还有另外一种方法,就是将index设为一致,然后再合并,比如:
In [17]:
import pandas as pd
import numpy as np
df1=pd.DataFrame({'animal':['dog','cat','cat','cow','dog'],'price':[55,79,73,62,40],'grade':['c','a','c','b','d']})
df2=pd.DataFrame({'animals':['dog','cat','cow'],'weight':[553,792,731]})
print '*'*30
print df1
print '*'*30
print df2
print '*'*30
one=df1.set_index('animal')
two=df2.set_index('animals')
print one
print '*'*30
print two
print '*'*30
print two.reindex(one.index)
print '*'*30
one['weight']=two.reindex(one.index) #新增一列的内容就是tworeindex后的value,填充过去了
print one
******************************
animal grade price
0 dog c 55
1 cat a 79
2 cat c 73
3 cow b 62
4 dog d 40
******************************
animals weight
0 dog 553
1 cat 792
2 cow 731
******************************
grade price
animal
dog c 55
cat a 79
cat c 73
cow b 62
dog d 40
******************************
weight
animals
dog 553
cat 792
cow 731
******************************
weight
animal
dog 553
cat 792
cat 792
cow 731
dog 553
******************************
grade price weight
animal
dog c 55 553
cat a 79 792
cat c 73 792
cow b 62 731
dog d 40 553
- isnull()的补充
前面提到如何使用isnull()函数去判断数据表中是否有空值:
In[18]:
print df
print df.isnull()*1
print np.sum(df.isnull()*1,axis=0) #axis=0意味着按列相加,axis=1意味着按行相加
np.sum(df.isnull()*1,axis=1) !=0
one two three
a 1 1 2
b 2 2 4
c 3 3 6
d NaN 4 NaN
one two three
a 0 0 0
b 0 0 0
c 0 0 0
d 1 0 1
one 1
two 0
three 1
dtype: int64
Out[18]:
a False
b False
c False
d True
dtype: bool
加上any参数,如isnull().any(axis=1)
,即可判断每一行是否有空值,返回布尔值。不定义axis,则默认按列检查。
9.改变数据类型
astype()可以改变数据类型,对于数据表中的某行某列,可以改变类型后再赋予自己,比如:df['a','b']=df['a','b'].astype(float)
结语
至此,我们已掌握了Python的基本知识。下一章我们将学习金融建模中的excel函数,敬请期待。
刺猬偷腥
2017年10月13日
to be continued.