Python數(shù)據(jù)分析_Pandas02_數(shù)據(jù)框的合并和重整

主要內(nèi)容:
  • 數(shù)據(jù)拼接:join、merge、contact、append
  • 數(shù)據(jù)重整:reshape -- stuck、unstuck
  • 數(shù)據(jù)透視表:pivot tables

數(shù)據(jù)拼接

1. concat

參數(shù)介紹:

pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False,
          keys=None, levels=None, names=None, verify_integrity=False,
          copy=True)

axis:要粘在哪個(gè)軸上。默認(rèn)0,粘貼行。
join:默認(rèn)outer,合集;inner,交集。
ignore_index:布爾型,默認(rèn)False。如果為T(mén)ure的話(huà),會(huì)重新分配index從0...n-1。
keys:一個(gè)序列,默認(rèn)None。建立等級(jí)索引,作為最外層的level。
levels:序列sequences構(gòu)成的list,默認(rèn)None。

示例:

In [41]: df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
    ...:                     'B': ['B0', 'B1', 'B2', 'B3'],
    ...:                     'C': ['C0', 'C1', 'C2', 'C3'],
    ...:                     'D': ['D0', 'D1', 'D2', 'D3']},
    ...:                     index=[0, 1, 2, 3])

In [42]: df2 = pd.DataFrame({'A': ['A4', 'A5', 'A6', 'A7'],
    ...:                     'B': ['B4', 'B5', 'B6', 'B7'],
    ...:                     'C': ['C4', 'C5', 'C6', 'C7'],
    ...:                     'D': ['D4', 'D5', 'D6', 'D7']},
    ...:                      index=[4, 5, 6, 7])
    ...:

In [43]: df3 = pd.DataFrame({'A': ['A8', 'A9', 'A10', 'A11'],
    ...:                     'B': ['B8', 'B9', 'B10', 'B11'],
    ...:                     'C': ['C8', 'C9', 'C10', 'C11'],
    ...:                     'D': ['D8', 'D9', 'D10', 'D11']},
    ...:                     index=[8, 9, 10, 11])
    ...:

In [44]: frames = [df1, df2, df3]

In [45]: result = pd.concat(frames)

In [46]: result
Out[46]:
      A    B    C    D
0    A0   B0   C0   D0
1    A1   B1   C1   D1
2    A2   B2   C2   D2
3    A3   B3   C3   D3
4    A4   B4   C4   D4
5    A5   B5   C5   D5
6    A6   B6   C6   D6
7    A7   B7   C7   D7
8    A8   B8   C8   D8
9    A9   B9   C9   D9
10  A10  B10  C10  D10
11  A11  B11  C11  D11

In [47]:  result2 = pd.concat(frames, keys=['x', 'y', 'z'])

In [48]: result2
Out[48]:
        A    B    C    D
x 0    A0   B0   C0   D0
  1    A1   B1   C1   D1
  2    A2   B2   C2   D2
  3    A3   B3   C3   D3
y 4    A4   B4   C4   D4
  5    A5   B5   C5   D5
  6    A6   B6   C6   D6
  7    A7   B7   C7   D7
z 8    A8   B8   C8   D8
  9    A9   B9   C9   D9
  10  A10  B10  C10  D10
  11  A11  B11  C11  D11

In [51]: result2.index    # result2的shape是(12,4),多重索引,如下:
Out[51]:
MultiIndex(levels=[['x', 'y', 'z'], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]],
           labels=[[0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]])

In [49]: result2.ix['y']                # .ix 等級(jí)索引
Out[49]:
    A   B   C   D
4  A4  B4  C4  D4
5  A5  B5  C5  D5
6  A6  B6  C6  D6
7  A7  B7  C7  D7

contact會(huì)生成一個(gè)copy,比較費(fèi)內(nèi)存。如果要用的話(huà),最好把所有要拼接的數(shù)據(jù)框放一list中,一次concat所有。像這樣:

frames = [ process_your_file(f) for f in files ]
result = pd.concat(frames)

2. append

和python中l(wèi)ist的append不同,這里的append不改變?cè)瓉?lái)的數(shù)據(jù)框,返回一個(gè)拼接后的copy。

In [57]: appended = df1.append([df2, df3])

In [58]: appended
Out[58]:
      A    B    C    D
0    A0   B0   C0   D0
1    A1   B1   C1   D1
2    A2   B2   C2   D2
3    A3   B3   C3   D3
4    A4   B4   C4   D4
5    A5   B5   C5   D5
6    A6   B6   C6   D6
7    A7   B7   C7   D7
8    A8   B8   C8   D8
9    A9   B9   C9   D9
10  A10  B10  C10  D10
11  A11  B11  C11  D11

In [59]: df1
Out[59]:
    A   B   C   D
0  A0  B0  C0  D0
1  A1  B1  C1  D1
2  A2  B2  C2  D2
3  A3  B3  C3  D3

添加一行:【注】ignore_index=True

可以添加Series或list(放著dicts的list)

In [80]: s2 = pd.Series(['X0', 'X1', 'X2', 'X3'],index=df1.columns)
In [83]: df1_s2 =  df1.append(s2,ignore_index=True)

In [84]: df1_s2
Out[84]:
    A   B   C   D
0  A0  B0  C0  D0
1  A1  B1  C1  D1
2  A2  B2  C2  D2
3  A3  B3  C3  D3
4  X0  X1  X2  X3

dicts = [{'A': 1, 'B': 2, 'C': 3, 'X': 4},
         {'A': 5, 'B': 6, 'C': 7, 'Y': 8}]
result = df1.append(dicts, ignore_index=True)

下面的merge和join是針對(duì)數(shù)據(jù)框合并的,一般都是列合并。

3. merge

參數(shù)介紹:

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,
         left_index=False, right_index=False, sort=True,
         suffixes=('_x', '_y'), copy=True, indicator=False)
         
left: 一個(gè)dataframe對(duì)象
right: 另一個(gè)dataframe對(duì)象
how: 可以是'left', 'right', 'outer', 'inner'. 默認(rèn)為inner。
on: 列名,兩個(gè)dataframe都有的列。如果不傳參數(shù),
    而且left_index和right_index也等于False,
    則默認(rèn)把兩者交叉/共有的列作為鏈接鍵(join keys)。
    可以是一個(gè)列名,也可以是包含多個(gè)列名的list。
left_on: 左邊dataframe的列會(huì)用做keys??梢允橇忻?,
    或者與dataframe長(zhǎng)度相同的矩陣array。
right_on: 右邊同上。
left_index: 如果為T(mén)ure,用左側(cè)dataframe的index作為
    連接鍵。如果是多維索引,level數(shù)要跟右邊相同才行。
right_index: 右邊同上。
sort: 對(duì)合并后的數(shù)據(jù)框排序,以連接鍵。
suffixes: 一個(gè)tuple,包字符串后綴,用來(lái)加在重疊的列名后面。
    默認(rèn)是('_x','_y')。
copy: 默認(rèn)Ture,復(fù)制數(shù)據(jù)。
indicator: 布爾型(True/FALSE),或是字符串。
    如果為T(mén)rue,合并之后會(huì)增加一列叫做'_merge'。
    是分類(lèi)數(shù)據(jù),用left_only, right_only, both來(lái)標(biāo)記
    來(lái)自左邊,右邊和兩邊的數(shù)據(jù)。

示例:

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

In [6]: right = pd.DataFrame({'key': ['K1', 'K2', 'K3', 'K4'],
   ...:                       'C': ['C0', 'C1', 'C2', 'C3'],
   ...:                       'D': ['D0', 'D1', 'D2', 'D3']})
   ...:

#默認(rèn)inner合并,只保留共同的部分。
In [7]: pd.merge(left, right, on='key')
Out[7]:
    A   B key   C   D
0  A1  B1  K1  C0  D0
1  A2  B2  K2  C1  D1
2  A3  B3  K3  C2  D2

#outer方式合并
In [8]: pd.merge(left, right, how='outer', on='key')
Out[8]:
     A    B key    C    D
0   A0   B0  K0  NaN  NaN
1   A1   B1  K1   C0   D0
2   A2   B2  K2   C1   D1
3   A3   B3  K3   C2   D2
4  NaN  NaN  K4   C3   D3

#indicator,用來(lái)標(biāo)示數(shù)據(jù)來(lái)源。
In [11]: In [8]: pd.merge(left, right, how='outer', on='key', indicator = 'indicator_colomn')
Out[11]:
     A    B key    C    D indicator_colomn
0   A0   B0  K0  NaN  NaN        left_only
1   A1   B1  K1   C0   D0             both
2   A2   B2  K2   C1   D1             both
3   A3   B3  K3   C2   D2             both
4  NaN  NaN  K4   C3   D3       right_only

4. Join

另一個(gè)便捷的合并數(shù)據(jù)框的方法。

參數(shù)介紹:

DataFrame.join(other, on=None, how='left', lsuffix='', rsuffix='', sort=False)

other:一個(gè)DataFrame、Series(要有命名),或者DataFrame組成的list。
on:列名,包含列名的list或tuple,或矩陣樣子的列
    (如果是多列,必須有MultiIndex)。
    跟上面的幾種方法一樣,用來(lái)指明依據(jù)哪一列進(jìn)行合并。
    如果沒(méi)有賦值,則依據(jù)兩個(gè)數(shù)據(jù)框的index合并。
how:合并方式, {‘left’, ‘right’, ‘outer’, ‘inner’},
    默認(rèn) ‘left’調(diào)用函數(shù)的數(shù)據(jù)框。
lsuffix:字符串。用于左側(cè)數(shù)據(jù)框的重復(fù)列。
    把重復(fù)列重新命名,原來(lái)的列名+字符串。
    【如果有重復(fù)列,必須添加這個(gè)參數(shù)?!?rsuffix:同上。右側(cè)。
sort:布爾型,默認(rèn)False。如果為T(mén)rue,將鏈接鍵(on的那列)按字母排序。

示例:

In [3]: left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
   ...:                      'B': ['B0', 'B1', 'B2'],
   ...:                      'D': ['D3', 'D4', 'D5']},
   ...:                      index=['K0', 'K1', 'K2'])
   ...:
   ...: right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
   ...:                       'D': ['D0', 'D2', 'D3']},
   ...:                       index=['K0', 'K2', 'K3'])
   ...:
   
In [5]: left.join(right, lsuffix='_left', rsuffix='_right')
Out[5]:
     A   B D_left    C D_right
K0  A0  B0     D3   C0      D0
K1  A1  B1     D4  NaN     NaN
K2  A2  B2     D5   C2      D2

In [8]: left.join(right, on='D', how='outer', lsuffix='_left', rsuffix='_right')
Out[8]:
     D    A    B D_left    C D_right
K0  D3   A0   B0     D3  NaN     NaN
K1  D4   A1   B1     D4  NaN     NaN
K2  D5   A2   B2     D5  NaN     NaN
K2  K0  NaN  NaN    NaN   C0      D0
K2  K2  NaN  NaN    NaN   C2      D2
K2  K3  NaN  NaN    NaN   C3      D3

#對(duì)比沒(méi)有'on'的情況。對(duì)于上面第8行輸出有點(diǎn)兒懵逼。
In [9]: left.join(right, how='outer', lsuffix='_left', rsuffix='_right')
Out[9]:
      A    B D_left    C D_right
K0   A0   B0     D3   C0      D0
K1   A1   B1     D4  NaN     NaN
K2   A2   B2     D5   C2      D2
K3  NaN  NaN    NaN   C3      D3

# 使用默認(rèn)索引的時(shí)候:
In [10]: left = pd.DataFrame({'A': ['A0', 'A1', 'A2'],
    ...:                      'B': ['B0', 'B1', 'B2'],
    ...:                      'D': ['D3', 'D4', 'D5']})
    ...: right = pd.DataFrame({'C': ['C0', 'C2', 'C3'],
    ...:                       'D': ['D0', 'D2', 'D3']})
    ...:

In [11]: left.join(right, lsuffix='_left', rsuffix='_right')
Out[11]:
    A   B D_left   C D_right
0  A0  B0     D3  C0      D0
1  A1  B1     D4  C2      D2
2  A2  B2     D5  C3      D3

合并數(shù)據(jù)框這些方法大同小異,選一個(gè)能滿(mǎn)足需要就行啦。


數(shù)據(jù)重整

pivot

用于生成一個(gè)數(shù)據(jù)透視表。

參數(shù)介紹:

DataFrame.pivot(index=None, columns=None, values=None)[source]

index:字符串或?qū)ο?,可選。列名,用來(lái)當(dāng)新數(shù)據(jù)框index的列,可以是多個(gè)列名的list。
columns:字符串或?qū)ο?。列名,?dāng)做新數(shù)據(jù)框的列。
values:字符串或?qū)ο?,可選。列名,生成新數(shù)據(jù)框的值。
    如果沒(méi)有指定,則使用余下的所有列,會(huì)生成等級(jí)索引列。

示例:

In [16]: df = pd.DataFrame({'foo': ['one','one','one','two','two','two'],
    ...:                    'bar': ['A', 'B', 'C', 'A', 'B', 'C'],
    ...:                    'baz': [1, 2, 3, 4, 5, 6]})

In [20]: df
Out[20]:
  bar  baz  foo
0   A    1  one
1   B    2  one
2   C    3  one
3   A    4  two
4   B    5  two
5   C    6  two

In [21]: df.pivot(index='foo', columns='bar', values='baz')
    ...:
Out[21]:
bar  A  B  C
foo
one  1  2  3
two  4  5  6

# 有多列數(shù)值的情況
In [22]: df['baz_2'] = df['baz']*2

In [23]: df.pivot(index='foo', columns='bar')
Out[23]:
    baz       baz_2
bar   A  B  C     A   B   C
foo
one   1  2  3     2   4   6
two   4  5  6     8  10  12

# 另一種選擇數(shù)值value的方法
In [24]: df.pivot(index='foo', columns='bar')['baz_2']
Out[24]:
bar  A   B   C
foo
one  2   4   6
two  8  10  12

升級(jí)版pivot:pandas.DataFrame.pivot_table。有更多的參數(shù)。個(gè)人感覺(jué)比較雞肋,復(fù)雜的分類(lèi)匯總有其他的函數(shù)可用。

stack 和 unstack

另一種重整數(shù)據(jù)的方法。stack和unstack是互逆方式。參數(shù)很簡(jiǎn)單。直接貼個(gè)例子好了

In [41]: df2 = df.pivot(index='foo', columns='bar')['baz_2']
    ...: df2
    ...:
Out[41]:
bar  A   B   C
foo
one  2   4   6
two  8  10  12

In [42]: stacked = df2.stack()

In [43]: stacked
Out[43]:
foo  bar
one  A       2
     B       4
     C       6
two  A       8
     B      10
     C      12
dtype: int64

In [44]: stacked.unstack()
Out[44]:
bar  A   B   C
foo
one  2   4   6
two  8  10  12
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容