Python数据分析摘要(2)-DataFrame数据的拓展,拼接与常见统计量

Python数据分析摘要(2)
声明:以下内容都是基于python3.8版本。


一、pandas.DataFrame在index或column两个维度上的拓展

pandas.DataFrame 做为一种数据存在类型,我们可以从index和column两个方向上对原有的pandas.DataFrame进行进一步拓展。
1.1 首先,我们考虑从column维度对pandas.DataFrame进行拓展。
基本公式:DataFrame[’’] = (,…)

我们首先设定初始化两个pandas.DataFrame,代码如下:

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
#初始化DataFrame
df = pd.DataFrame([[10,20],[20,40],[30,50],[70,90],], index = ['a','b','c','d'], columns = ['number','post'])
df1 = pd.DataFrame([101,202,303,404], columns = ['number'])
print(df)
print(df1)

我们会得到df,

   number  post
a      10    20
b      20    40
c      30    50
d      70    90

以及df1,

   number
0     101
1     202
2     303
3     404

现在我们对df新增一列ID,并赋值1.1,1.2,1.3,1.4
代码如下,

df['ID'] = (1.1,1.2,1.3,1.4)
print(df)

得到新的df,

   number  post   ID
a      10    20  1.1
b      20    40  1.2
c      30    50  1.3
d      70    90  1.4

1.2 我们考虑从index维度对pandas.DataFrame进行拓展。
基本公式:
新DataFrame = 旧DataFrame .append(pd.DataFrame({“number”:[,…],“ID”:[,…]},index = [,…]))
易错点:一定记得储存到新的变量中!!!

我们继续沿用刚刚初始化的df,我们这次需要命名一个新的索引名,z,把df进行进一步扩充。

代码如下:

df = df.append(pd.DataFrame({
    
    "number":2.1,"ID":2.2},index = ['z']))
print(df)

结果如下,

   number  post   ID
a    10.0  20.0  1.1
b    20.0  40.0  1.2
c    30.0  50.0  1.3
d    70.0  90.0  1.4
z     2.1   NaN  2.2

二、pandas.DataFrame的join, group,merge和numpy.concatenate方法

在进行数据的过程中,我们经常用到表的级联和分组。python的join和group方法的实现原理与sql语言相差无几。但在语言表达上有些区别,需要注意。

2.1我们先来介绍一下,常见的join方法。

【重点:join只能做左右拼接,不能做上下拼接,缺失值用NAN补全;优点是可以同时拼接好几个DataFrame,且相较merge和concatenate方法速度更快】

2.1.1 join的第一种方法,先设置两个需要级联表的key(也称为key attribute),再级联。(默认为左级联,以主表的index作为key attribute,所有非key attribute 的列空位用null值补全,若有重名列用lsuffix和rsuffix的命名区分)

基本公式:
新pandas.DataFrame=pandas.DataFrame1.set_index().join(pandas.DataFrame2.set_index(),lsuffix=’_caller’, rsuffix=’_other’)

代码如下:

df2=df.set_index('number').join(df1.set_index('number'),lsuffix='_caller', rsuffix='_other')
df3=df1.set_index('number').join(df.set_index('number'),lsuffix='_caller', rsuffix='_other')
print(df2)
print(df3)

df2得到结果如下,

        post   ID
number           
10.0    20.0  1.1
20.0    40.0  1.2
30.0    50.0  1.3
70.0    90.0  1.4
2.1      NaN  2.2

我们可以清楚看到,两个表根据number这一列进行级联,并且默认为左级联,但右表即df1的number一列值没有跟df的number相等的值存在,所以,我们得到的df2,这个新的级联表和df是一样的。

同理,我们可以得到df3表,因为df1中不存在post 和 ID 两列,但df中存在。所以,我们用null值补全空位。
df3结果如下,

        post  ID
number          
101      NaN NaN
202      NaN NaN
303      NaN NaN
404      NaN NaN

但当df1的key attribute额df的key attribute存在相同值时,我们会得到如下级联表。
代码如下,

df.iloc[0,0] = 101
df3=df1.set_index('number').join(df.set_index('number'),lsuffix='_caller', rsuffix='_other')
print(df3)

结果如下,

        post   ID
number           
101     20.0  1.1
202      NaN  NaN
303      NaN  NaN
404      NaN  NaN

或者,我把df1也利用column维度进行扩充,再与df级联,我们看一下效果。
得到的新的df和df1分别为,

   number  post   ID
a   101.0  20.0  1.1
b    20.0  40.0  1.2
c    30.0  50.0  1.3
d    70.0  90.0  1.4
z     2.1   NaN  2.2
   number   ID
0     101  1.1
1     202  1.2
2     303  1.5
3     404  1.3
df1['ID'] = [1.1,1.2,1.5,1.3]
df3=df1.set_index('number').join(df.set_index('number'),lsuffix='_caller', rsuffix='_other')
print(df3)

因为两个表中都存在key attribute以外的相同的column,所以我们得到加后缀的额外列。
结果如下,

        ID_caller  post  ID_other
number                           
101           1.1  20.0       1.1
202           1.2   NaN       NaN
303           1.5   NaN       NaN
404           1.3   NaN       NaN

2.1.2 join的第二种方法,直接级联。(默认为左级联,以主表的index为key attribute,所有非key attribute 的列空位用null值补全,若有重名列用lsuffix和rsuffix的命名区分)
基本公式:pandas.DataFrame1.join(pandas.DataFrame2, on=None,how=’‘lsuffix=’’, rsuffix=’’, sort=False)

得到
我们继续利用已经得到的df和df1,进行直接级联,并指定级联方式为右级联。

df4 = df.join(df1,lsuffix='_caller', rsuffix='_other',how = 'right')
print(df4)

因为这时我们并没有指定 key,所以用index作为key attribute,得到结果如下,

   number_caller  post  ID_caller  number_other  ID_other
0            NaN   NaN        NaN           101       1.1
1            NaN   NaN        NaN           202       1.2
2            NaN   NaN        NaN           303       1.5
3            NaN   NaN        NaN           404       1.3

2.2 我们接下来介绍一下,group分组方法。
基本公式:pandas.DataFrame.groupby([<目标attribute 1>,<目标attribute2>…]),再按其他column做对应运算。(前提是我们可以先设置一个新列,并按分组要求对每行打上分组标签)

首先我们生成包含9行4列的标准正态分布的伪随机数ndarrage,再用DatatimeIndex作为索引,并以期末取值,代码如下,

a = np.random.standard_normal((9,4))
a = a.round(6)
df6 = pd.DataFrame(a)
#生成DatatimeIndex索引,以期末取值
dates = pd.date_range('2016-01-01','2019-12-31',freq = 'Y')
df6.columns = dates
print(df6)

输出结果如下,

   2016-12-31  2017-12-31  2018-12-31  2019-12-31
0    0.453243   -0.068952    1.545494    0.510076
1    0.837713   -1.465241   -0.740922   -1.524568
2   -0.384375    1.165462   -0.273746    0.508105
3   -0.143992   -0.554521   -0.168501    1.020890
4    1.116631    0.633020    0.588792   -0.410130
5    1.824028    0.216709    1.293103   -2.147095
6   -0.085606   -0.613363    0.988932   -1.005342
7    0.463741    0.336018    0.202069   -0.609974
8    0.884615    0.164266    0.577031    0.322006

然后我们把上边表格按index分组,前8个两两一组,最后一个一组,用quarter表示。
代码如下,

df6['quator'] = (1,1,2,2,3,3,4,4,5)

最后求出每组的在每个column下的均值,代码如下,

print(df6.groupby('quator').mean())

结果如下,

        2016-12-31  ...  2019-12-31
quator              ...            
1        -0.971370  ...   -0.098655
2         0.758503  ...   -0.735746
3        -0.564706  ...   -0.756345
4         0.126177  ...   -0.114578
5         2.081236  ...   -0.433217

[5 rows x 4 columns]

2.3 我们接下来介绍一下,merge方法。

【重点:merge只能做左右拼接,不能做上下拼接,缺失值用NAN补全;与join方法效果类似】
【易错点:如果左右两个DataFrame没有对应的拼接依据,则报错】

基本公式:pandas.merge(<目标pandas.DataFrame 左>,<目标pandas.DataFrame 右>,再按 left_on/right_on/on 上的列名/索引作为拼接依据,做how 上的方法作为拼接方法,包括“inner”,“outer”,“left”,"right"做对应方法拼接,默认为“inner”。另外,left_on /right_on 与 left_index/right_index 可以混合使用来确定拼接依据, 其中left_index/right_index 为True/False。最后可以使用sort=True,对拼接依据进行排序【注:从小到大】)

首先我们生成df1,df2 代码如下,

df1 = pd.DataFrame({
    
    'A': ['A0', 'A1', 'A2', 'A3'],
                     'B': ['B0', 'B1', 'B2', 'B3'],
                   'key': ['K0', 'K1', 'K0', 'K1']})


df2 = pd.DataFrame({
    
    'C': ['C0', 'C1'],
                      'D': ['D0', 'D1'],
                    'k':['K0', 'K1']}) 
print(df1)
print(df2)

输出结果如下,

    A   B key
0  A0  B0  K0
1  A1  B1  K1
2  A2  B2  K0
3  A3  B3  K1
    C   D   k
0  C0  D0  K0
1  C1  D1  K1

然后我们把df1和df2左右拼接,如果我们把on 赋值为 df1 的 “B”,则会报错;
如下图
在这里插入图片描述
原因是df2列表没有“B”这一列名。
所以,我们以df1的“key” 和 df2的 “k”作为拼接依据,采用left方法,并根据拼接依据的值进行表格排序。

代码如下,

df3 = pd.merge(df1, df2, left_on = "key",right_on = "k", how = "left",sort = True)
print(df3)

最后得出结果,如下

   A   B key   C   D   k
0  A0  B0  K0  C0  D0  K0
1  A2  B2  K0  C0  D0  K0
2  A1  B1  K1  C1  D1  K1
3  A3  B3  K1  C1  D1  K1

拼接拓展:pandas.merge() VS pandas.DataFrame.join() VS numpy.concatenate()
[重点:numpy.concatenate()可以进行上下或者左右拼接,由axis参数确定;而pandas.merge 和 pandas.join 只能进行左右拼接!]

[易错点:numpy.concatenate(), 而不是pandas.concatenate(),所以numpy.concatenate() 只能代入 np.array型数据,同时适用DataFrame型数据!]
[易错点:要求numpy.concatenate()里的两个np.array 一定在拼接维度上,维度相等!否则,报错。]

首先我们生成np1,np2 代码如下,

np1 = np.array([[1,2,3],[4,5,6]])


np2 = np.array([[11,22,33,44],[55,66,77,88],[99,00,111,222]])    

print(np1)
print(np2)

输出结果如下,

[[1 2 3]
 [4 5 6]]
[[ 11  22  33  44]
 [ 55  66  77  88]
 [ 99   0 111 222]]

然后我们把np1和np2上下拼接,同时拼接方向为np1的纵向,代码如下

np3 = np.concatenate((np1, np2.T),axis= 0)
print(np3)

最后得出结果,如下

[[  1   2   3]
 [  4   5   6]
 [ 11  55  99]
 [ 22  66   0]
 [ 33  77 111]
 [ 44  88 222]]

三、pandas.DataFrame的常用统计方法

pandas.DataFrame有4个常用内置统计方法,都是以列做运算
求列和:pandas.DataFrame.sum()
求列均值:pandas.DataFrame.mean()
求列累加和:pandas.DataFrame.cumsum()
求列统计量(包括列元素个数,列均值,列标准差,列最小值,列的百分位数和列最大值):pandas.DataFrame.describe()

我们继续用已经获得的数据进行展示一下,
代码如下,

a = np.random.standard_normal((9,4))
a = a.round(6)
df6 = pd.DataFrame(a)
print(df6.sum())
print(df6.mean())
print(df6.cumsum())
print(df6.describe())

结果如下,

   2016-12-31  2017-12-31  2018-12-31  2019-12-31
0   -1.101220   -1.349005    0.606338   -1.322234
1   -1.129266    0.632621   -1.460356    0.296983
2   -0.791004    0.312555    0.694449    0.266228
3   -0.541898    0.061317   -1.061466   -0.680826
4   -0.539163    0.351453    1.636628   -0.664157
5    0.803651    0.748810    0.087098    0.386566
6   -1.656814    0.882635    0.797272   -0.959593
7    0.632578   -1.498644    1.546371   -0.404477
8    1.180458    0.882217    0.190661    0.354593
2016-12-31   -3.142678
2017-12-31    1.023959
2018-12-31    3.036995
2019-12-31   -2.726917
Freq: A-DEC, dtype: float64
2016-12-31   -0.349186
2017-12-31    0.113773
2018-12-31    0.337444
2019-12-31   -0.302991
Freq: A-DEC, dtype: float64
   2016-12-31  2017-12-31  2018-12-31  2019-12-31
0   -1.101220   -1.349005    0.606338   -1.322234
1   -2.230486   -0.716384   -0.854018   -1.025251
2   -3.021490   -0.403829   -0.159569   -0.759023
3   -3.563388   -0.342512   -1.221035   -1.439849
4   -4.102551    0.008941    0.415593   -2.104006
5   -3.298900    0.757751    0.502691   -1.717440
6   -4.955714    1.640386    1.299963   -2.677033
7   -4.323136    0.141742    2.846334   -3.081510
8   -3.142678    1.023959    3.036995   -2.726917
       2016-12-31  2017-12-31  2018-12-31  2019-12-31
count    9.000000    9.000000    9.000000    9.000000
mean    -0.349186    0.113773    0.337444   -0.302991
std      0.986478    0.914638    1.050823    0.646661
min     -1.656814   -1.498644   -1.460356   -1.322234
25%     -1.101220    0.061317    0.087098   -0.680826
50%     -0.541898    0.351453    0.606338   -0.404477
75%      0.632578    0.748810    0.797272    0.296983
max      1.180458    0.882635    1.636628    0.386566

总结

以上就是今天的经验分享,从拓展已有pandas.DataFrame到两个常用方法,join和groupby,最后又介绍了一下panadas常用的统计方法。相信这些经验都能帮助你日后在数据分析中大展身手~ 如果觉得今天的分析对你有帮助,请点个赞鼓励一下吧~~

猜你喜欢

转载自blog.csdn.net/dylan_young/article/details/112150031