1. 程式人生 > >Pandas學習2 --- 資料型別Series、DataFrame

Pandas學習2 --- 資料型別Series、DataFrame

Pandas的資料型別

  • Series(一維資料結構)
  • Dataframe

Series --- 帶標籤的一維陣列

常用的初始化方法:

  • 可迭代物件
  • np陣列
  • 字典物件
  • 標量

一、Series

1. Series初始化

匯入

import pandas as pd
import numpy as np
s = pd.Series([1, 2, 3])
type(s)
pandas.core.series.Series
s
0    1
1    2
2    3
dtype: int64

通過可迭代物件建立Series

 pd.Series(range(5))
0    0
1    1
2    2
3    3
4    4
dtype: int64

通過numpy陣列建立Series

t = np.random.randint(5, 15, size=(8))
pd.Series(t)
0    11
1     9
2     6
3     7
4    11
5    12
6     6
7    14
dtype: int64

通過標量建立

pd.Series(100, index=['a', 5, b'sd'])
a        100
5        100
b'sd'    100
dtype: int64

使用字典自帶索引

pd.Series({100:165, 'asdf':961})
100     165
asdf    961
dtype: int64

2. Series資料屬性

2.1 索引

獲得索引

s = pd.Series([7,8,9], index=[1,2,3])
s.index
Int64Index([1, 2, 3], dtype='int64')
s.index = ['a', 'b', 'c']
s
a    7
b    8
c    9
dtype: int64
可以手動建立Index物件(數量必須匹配)
index = pd.Index(['aaaa', 'bbbb', 'cccc'])
pd.Series([7,8,9], index=index)
aaaa    7
bbbb    8
cccc    9
dtype: int64

2.2 值

返回資料

s.values
array([7, 8, 9])
s
a    7
b    8
c    9
dtype: int64

2.3 尺寸

s.size
3
s.dtype
dtype('int64')

2.4 其他

Series可以指定name

index = pd.Index(['a', 'b', 'c'], name = 'Index名字')
s = pd.Series([1,2,3], index=[1,2,3], name='"Series名字"')
s
1    1
2    2
3    3
Name: "Series名字", dtype: int64

索引可以指定name屬性

s.index = index
s
My_Index
a    1
b    2
c    3
Name: "Series名字", dtype: int64

head 和 tail ,預設(n=5)

s.head(2)
1    1
2    2
Name: "Series名字", dtype: int64
s.tail(100)
1    1
2    2
3    3
Name: "Series名字", dtype: int64
test_np = np.random.randint(0, 15, size = 10)
test_np
array([3, 5, 9, 6, 1, 8, 9, 9, 2, 1])
test_pd = pd.Series(test_np)
test_pd
0     6
1    11
2     4
3     3
4     4
5     9
6     4
7     7
8    11
9     5
dtype: int64
test_np[5]
9
test_pd[5]
9
test_np[5] == test_pd[5]
True

3. Series運算

test_pd
0     7
1    12
2     5
3     4
4     5
5    10
6     5
7     8
8    12
9     6
dtype: int64
test_pd + 1
0     8
1    13
2     6
3     5
4     6
5    11
6     6
7     9
8    13
9     7
dtype: int64
test_pd + test_pd
0    14
1    24
2    10
3     8
4    10
5    20
6    10
7    16
8    24
9    12
dtype: int64

Series按照 index 計算,缺失則返回結果NaN(not a number)

s1 = pd.Series([1,2,3], index=[1,2,3])
s2 = pd.Series([1,2,3], index=[2,3,4])
s1 + s2
1    NaN
2    3.0
3    5.0
4    NaN
dtype: float64

使用函式方式運算,如果需要處理不匹配值,那麼對Series物件填充索引,指定填充值,並進行運算

s1.add(s2, fill_value=100000)
1    100001.0
2         3.0
3         5.0
4    100003.0
dtype: float64

幾個特殊浮點數, 以及空值的判斷

s = pd.Series([1, 2, 3, float('NaN'), np.NaN])
s.isnull()
0    False
1    False
2    False
3     True
4     True
dtype: bool

nd 和 pd 在計算時對空值的的處理不同

  • numpy會產生空值()
  • pandas忽略空值
t = np.array([1, 2, 3, float('NaN'), np.NaN])
t.sum()
nan
s.sum()
6.0

4. 提取元素

  • 通過索引提取元素
  • 通過標籤陣列布林陣列提取元素(推薦)
a = np.array([1, 2, 3])
b = pd.Series(a, index = [0,1,2])
index1 = [0, 1, 2]
index2 = [False, True, True]
b[index1]
0    1
1    2
2    3
dtype: int64
b[index2]
1    2
2    3
dtype: int64

注意:

  • 訪問可以使用標籤索引,也可以使用位置索引
  • 建立時指定的標籤,稱為標籤索引,如果標籤索引是數值型別,替換原先預設的位置索引(位置索引失效)

5. 標籤索引(loc)和位置索引(iloc) --- 避免索引混淆

b.loc[0]
1
b.iloc[1]
2
# test_np = np.random.randint(0, 15, size = 10)
test_np = np.arange(15)
test_pd = pd.Series(test_np)

test_pd.loc[4:8].values # 標籤索引會前閉後閉
array([4, 5, 6, 7, 8])
test_pd.iloc[4:8].values # 標籤索引會前閉後開
array([4, 5, 6, 7])
test_np[4:8] # np索引前閉後開
array([4, 5, 6, 7])
test_np[4:80]
array([ 4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])

6. 數值操作

  • 獲取值
  • 修改值
  • 增加索引-值
  • 刪除索引-值
s = pd.Series([1, 2, 3, float('NaN'), np.NaN])
s.loc['a'] = 'a'
s
0      1
1      2
2      3
3    NaN
4    NaN
a      a
dtype: object
s.drop('a') # 建立新的刪除物件
0      1
1      2
2      3
3    NaN
4    NaN
dtype: object
s
0      1
1      2
2      3
3    NaN
4    NaN
a      a
dtype: object
s.drop(['a', 3], inplace=True) # 可以這樣子刪除,所有的inplace引數都預設為False,即返回新物件
s
0      1
1      2
2      3
4    NaN
dtype: object

9. 其他

  • unique --- 去重,但是不排序
  • value_counts --- 計數
s = pd.Series([1, 10, -2, -5, 20, 10, -5])
s.unique()
array([ 1, 10, -2, -5, 20])
s.value_counts(ascending=True)
 1     1
-2     1
 20    1
 10    2
-5     2
dtype: int64

二、DataFrame型別

1. DataFrame建立

多維資料型別,常用在二維情況,包含行標籤和列標籤。二維DaraFrame的建立方式如下:

  • 二維陣列結構(列表,ndarray,DataFrame等)
  • 字典型別,key為列標籤,value為一維資料結構
df1 = pd.DataFrame([[11, 21, 31], [99, 88, 77]])
df2 = pd.DataFrame([[11, 21, 31, 41], [99, 88, 77, 66]])
df1
0 1 2
0 11 21 31
1 99 88 77
print(df1)
    0   1   2
0  11  21  31
1  99  88  77

IPython的擴充套件內建函式display() 可以把多個數據美化呈現方式

display(df1)
display(df2)
0 1 2
0 11 21 31
1 99 88 77
0 1 2 3
0 11 21 31 41
1 99 88 77 66

DataFrame使用的是列向量,因此通過字典建立,Key是列表簽名

di = {
    "名字":['a', 'b', 'c', 'd'],
    '年齡':[32, 23, 45, 76],
    '班級':8,
    '成績':np.random.randint(0,100,4)
}
df = pd.DataFrame(di)
df
名字 年齡 成績 班級
0 a 32 31 8
1 b 23 46 8
2 c 45 95 8
3 d 76 67 8

index是行標籤, columns是列標籤

# df.index = ['張三', '李四', '王五', '李六']
df.columns = ["學生名字", '學生年齡', '學生成績', '學生班級']
df
學生名字 學生年齡 學生成績 學生班級
0 a 32 31 8
1 b 23 46 8
2 c 45 95 8
3 d 76 67 8

2. 抽取資料——抽樣

從頭和尾取資料

df.head(n=2)
名字 年齡 成績 班級
0 a 32 51 8
1 b 23 53 8
df.tail(n=2)
名字 年齡 成績 班級
2 c 45 63 8
3 d 76 79 8

隨機取樣

df.sample(n=2, frac=None, replace=False, weights=None, random_state=None, axis=None) # 預設不放回抽樣,抽取1個
名字 年齡 成績 班級
0 a 32 51 8
3 d 76 79 8
df.sample(n=10, replace=True, random_state=456) # random_state是隨機數種子; replace=True 是放回抽樣
名字 年齡 成績 班級
3 d 76 79 8
1 b 23 53 8
3 d 76 79 8
1 b 23 53 8
2 c 45 63 8
3 d 76 79 8
0 a 32 51 8
2 c 45 63 8
3 d 76 79 8
2 c 45 63 8
df.sample(n=10, replace=True, random_state=456) # random_state是隨機數種子; replace=True 是放回抽樣
名字 年齡 成績 班級
3 d 76 79 8
1 b 23 53 8
3 d 76 79 8
1 b 23 53 8
2 c 45 63 8
3 d 76 79 8
0 a 32 51 8
2 c 45 63 8
3 d 76 79 8
2 c 45 63 8

3. DataFrame屬性

  • index --- 行索引
  • columns --- 列索引
  • values --- 資料,二維ndarray資料
  • shape --- 形狀
  • ndim --- 維數
  • dtypes --- 資料型別(ndarray是一個能儲存的所有元素的唯一型別,DataFrame每一列一個型別)
df.index
RangeIndex(start=0, stop=4, step=1)
df.columns
Index(['名字', '年齡', '成績', '班級'], dtype='object')
df.values
array([['a', 32, 51, 8],
       ['b', 23, 53, 8],
       ['c', 45, 63, 8],
       ['d', 76, 79, 8]], dtype=object)
df.shape
(4, 4)
df.ndim
2

返回的資料為Series型別

df.dtypes
名字    object
年齡     int64
成績     int64
班級     int64
dtype: object

4. 行、列操作:

  • 可以通過index和columns提出特定資料
  • 可以為index和columns建立name
  • 直接中括號索引獲取列,loc和iloc獲取行(Series)

4.1 獲取行、列

di = {
    "名字":['a', 'b', 'c', 'd'],
    '年齡':[32, 23, 45, 76],
    '班級':8,
    '成績':np.random.randint(0,100,4)
}
df = pd.DataFrame(di)
df
名字 年齡 成績 班級
0 a 32 68 8
1 b 23 33 8
2 c 45 35 8
3 d 76 11 8

獲取一個數據

df.loc[0, '名字']
'a'

獲取一行

df[ '名字']
0    a
1    b
2    c
3    d
Name: 名字, dtype: object

df [ ] 訪問多列

df[['名字', '年齡']]
名字 年齡
0 a 32
1 b 23
2 c 45
3 d 76

獲取一行,每一行是一個Series型別

df.loc[1]
名字     b
年齡    23
成績    33
班級     8
Name: 1, dtype: object

訪問多行

df.loc[[1,2,3]]
名字 年齡 成績 班級
1 b 23 33 8
2 c 45 35 8
3 d 76 11 8

4.2 增加行、列

4.2.1 獲取某一列,Series的索引name為DataFrame列標籤名字

df['@'] = [1,2,3,4]
df
名字 年齡 成績 班級 @
0 a 32 68 8 1
1 b 23 33 8 2
2 c 45 35 8 3
3 d 76 11 8 4

4.2.2 新增一列

df['@']
0    1
1    2
2    3
3    4
Name: @, dtype: int64
df.index
RangeIndex(start=0, stop=4, step=1)
df.index.name = '行索引名'
df.columns.name = '列索引名'
df
列索引名 名字 年齡 成績 班級 @
行索引名
0 a 32 68 8 1
1 b 23 33 8 2
2 c 45 35 8 3
3 d 76 11 8 4

新增一個求和列

df1 = pd.DataFrame({
    '蘋果':[1,2,3],
    '香蕉':[4,5,6],
    '葡萄':[7,8,9],
})
df1['總和'] = df1['蘋果'] + df1['香蕉'] + df1['葡萄']
df1
蘋果 葡萄 香蕉 總和
0 1 7 4 12
1 2 8 5 15
2 3 9 6 18

4.2.3 刪除列

df.pop('@')
行索引名
0    1
1    2
2    3
3    4
Name: @, dtype: int64

4.2.4 獲取行

df.drop([1,2], axis='index', inplace=False) #返回新物件,不inplace修改
列索引名 學生名字 學生年齡 學生成績 學生班級
行索引名
0 a 32 31 8
3 d 76 67 8
df.loc[[2, 3]] # 推薦使用標籤名稱獲取物件
列索引名 學生名字 學生年齡 學生成績 學生班級
行索引名
2 c 45 95 8
3 d 76 67 8
df.iloc[[2, 3]] # 不推薦使用
列索引名 學生名字 學生年齡 學生成績 學生班級
行索引名
2 c 45 95 8
3 d 76 67 8

4.2.5 增加一行,需要新增的Series資料必須含有name(對應行標籤)

di = {
    "名字":['a', 'b', 'c', 'd'],
    '年齡':[32, 23, 45, 76],
    '班級':8,
    '成績':np.random.randint(0,100,4)
}
df = pd.DataFrame(di)
row = pd.Series([ 's', 45, 65, 8], name='new', index=['名字', '年齡', '成績', '班級'])
df.append(row )
名字 年齡 成績 班級
0 a 32 87 8
1 b 23 74 8
2 c 45 36 8
3 d 76 13 8
new s 45 65 8
di = {
    "名字":['a', 'b', 'c', 'd'],
    '年齡':[32, 23, 45, 76],
    '班級':8,
    '成績':np.random.randint(0,100,4)
}
dff = pd.DataFrame(di)
row = pd.Series([ 's', 45, 65, 8], name='new', index=['名字', '年齡', '成績', '班級'])
dff.append(row, ignore_index=True)
名字 年齡 成績 班級
0 a 32 6 8
1 b 23 8 8
2 c 45 93 8
3 d 76 73 8
4 s 45 65 8

在增加多行的時候,優先使用concat,效能更好。

pd.concat((df, dff), axis=0, ignore_index=False)
名字 年齡 成績 班級
0 a 32 51 8
1 b 23 53 8
2 c 45 63 8
3 d 76 79 8
0 a 32 6 8
1 b 23 8 8
2 c 45 93 8
3 d 76 73 8
result = pd.concat((df, dff), axis=1, ignore_index=False)
result
名字 年齡 成績 班級 名字 年齡 成績 班級
0 a 32 51 8 a 32 6 8
1 b 23 53 8 b 23 8 8
2 c 45 63 8 c 45 93 8
3 d 76 79 8 d 76 73 8

4.2.6 刪除l列、行

result.drop(['名字', '班級'], axis=1)
年齡 成績 年齡 成績
0 32 51 32 6
1 23 53 23 8
2 45 63 45 93
3 76 79 76 73

4.2.7 混合操作

可以先獲取行,也可以現貨區列

  • drop方法可以刪除行和列;
  • df[索引]針對列操作,不支援位置索引,只支援列標籤;
  • df.loc[索引]、df.iloc[索引]針對行操作;
  • df[切片]不推薦【對行操作,既支援位置索引,也支援標籤索引; 此外,和第二條衝突,切片索引變成了行操作不利於記憶】
  • df[[列表]] 也存在歧義,如果是【標籤陣列- 列操作】【布林陣列- 行操作】
df = pd.DataFrame({
    '蘋果':[1,2,3],
    '香蕉':[4,5,6],
    '葡萄':[7,8,9],
})
df['總和'] = df['蘋果'] + df['香蕉'] + df['葡萄']
df
蘋果 葡萄 香蕉 總和
0 1 7 4 12
1 2 8 5 15
2 3 9 6 18
df['蘋果'].loc([0])
<pandas.core.indexing._LocIndexer at 0x7fd51e4b37f0>
df[['蘋果', '葡萄']].loc[[0,2]]
蘋果 葡萄
0 1 7
2 3 9

切片訪問行

df.iloc[0:1]
蘋果 葡萄 香蕉 總和
0 1 7 4 12
df.iloc[0]
蘋果     1
葡萄     7
香蕉     4
總和    12
Name: 0, dtype: int64

4.2.8 標籤名,name屬性的轉換

  • 如果拿出列資料,
  • 如果拿出行資料,
df = pd.DataFrame({
    '蘋果':[1,2,3],
    '香蕉':[4,5,6],
    '葡萄':[7,8,9],
})
df['總和'] = df['蘋果'] + df['香蕉'] + df['葡萄']
df
蘋果 葡萄 香蕉 總和
0 1 7 4 12
1 2 8 5 15
2 3 9 6 18
df.loc[0]
蘋果     1
葡萄     7
香蕉     4
總和    12
Name: 0, dtype: int64
df[[True, False, False]]
蘋果 葡萄 香蕉 總和
0 1 7 4 12
df['蘋果']
0    1
1    2
2    3
Name: 蘋果, dtype: int64

5. 計算

df1 = pd.DataFrame(np.arange(24).reshape(4,6))
df2 = pd.DataFrame(np.arange(100, 124).reshape(4,6))

轉置

df1.T
0 1 2 3
0 0 6 12 18
1 1 7 13 19
2 2 8 14 20
3 3 9 15 21
4 4 10 16 22
5 5 11 17 23

加法

df1 + df2
0 1 2 3 4 5
0 100 102 104 106 108 110
1 112 114 116 118 120 122
2 124 126 128 130 132 134
3 136 138 140 142 144 146

加法對不齊,產生NaN

df2.index = [0, 1, 3, 4]
df2.columns = [0, 1, 2, 3, 4, 6]
df1 + df2
0 1 2 3 4 5 6
0 100.0 102.0 104.0 106.0 108.0 NaN NaN
1 112.0 114.0 116.0 118.0 120.0 NaN NaN
2 NaN NaN NaN NaN NaN NaN NaN
3 130.0 132.0 134.0 136.0 138.0 NaN NaN
4 NaN NaN NaN NaN NaN NaN NaN
df1.add(df2, fill_value=0)
0 1 2 3 4 5 6
0 100.0 102.0 104.0 106.0 108.0 5.0 105.0
1 112.0 114.0 116.0 118.0 120.0 11.0 111.0
2 12.0 13.0 14.0 15.0 16.0 17.0 NaN
3 130.0 132.0 134.0 136.0 138.0 23.0 117.0
4 118.0 119.0 120.0 121.0 122.0 NaN 123.0

DaraFram 和 Series 加法

--- 行和列操作都可以操作

s = pd.Series([100, 200, 300, 400, 500], index = np.arange(5))
df1
0 1 2 3 4 5
0 0 1 2 3 4 5
1 6 7 8 9 10 11
2 12 13 14 15 16 17
3 18 19 20 21 22 23

預設列對齊

df1 + s
0 1 2 3 4 5
0 100.0 201.0 302.0 403.0 504.0 NaN
1 106.0 207.0 308.0 409.0 510.0 NaN
2 112.0 213.0 314.0 415.0 516.0 NaN
3 118.0 219.0 320.0 421.0 522.0 NaN

也可以行操作

df1.add(s,  axis='index')
0 1 2 3 4 5
0 100.0 101.0 102.0 103.0 104.0 105.0
1 206.0 207.0 208.0 209.0 210.0 211.0
2 312.0 313.0 314.0 315.0 316.0 317.0
3 418.0 419.0 420.0 421.0 422.0 423.0
4 NaN NaN NaN NaN NaN NaN

7. 排序

  • 索引排序
  • 值排序
df = pd.DataFrame(np.arange(24).reshape(4,6), index=[5, 6, 2, 4], columns=[6,1,7,3, 4,2])
df
6 1 7 3 4 2
5 0 1 2 3 4 5
6 6 7 8 9 10 11
2 12 13 14 15 16 17
4 18 19 20 21 22 23
df.sort_index(axis=1, ascending=False) # 列操作,降序操作
7 6 4 3 2 1
5 2 0 4 3 5 1
6 8 6 10 9 11 7
2 14 12 16 15 17 13
4 20 18 22 21 23 19
df.sort_index(axis=0, ascending=False)
6 1 7 3 4 2
6 6 7 8 9 10 11
5 0 1 2 3 4 5
4 18 19 20 21 22 23
2 12 13 14 15 16 17
df.sort_values(5, axis=1, ascending=False, inplace=False) # 行操作,降序操作 ************易混淆*****************
2 4 3 7 1 6
5 5 4 3 2 1 0
6 11 10 9 8 7 6
2 17 16 15 14 13 12
4 23 22 21 20 19 18

8. 統計方法

  • mean / sum / count / median
  • max / min
  • cumsum / cumprod
  • argmax / argmin (所在索引, 老式不推薦)
  • idxmax / idxmin (所在索引,推薦)
  • var / std (標準差, 方差)
  • corr / cov (相關係數, 協方差)
df = pd.DataFrame(np.arange(24).reshape(4,6))
df
0 1 2 3 4 5
0 0 1 2 3 4 5
1 6 7 8 9 10 11
2 12 13 14 15 16 17
3 18 19 20 21 22 23
df.mean(axis='columns')
0     2.5
1     8.5
2    14.5
3    20.5
dtype: float64
df.idxmax()
0    3
1    3
2    3
3    3
4    3
5    3
dtype: int64
df.var
<bound method DataFrame.var of     0   1   2   3   4   5
0   0   1   2   3   4   5
1   6   7   8   9  10  11
2  12  13  14  15  16  17
3  18  19  20  21  22  23>
 df.std
<bound method DataFrame.std of     0   1   2   3   4   5
0   0   1   2   3   4   5
1   6   7   8   9  10  11
2  12  13  14  15  16  17
3  18  19  20  21  22  23>
df.corr()
0 1 2 3 4 5
0 1.0 1.0 1.0 1.0 1.0 1.0
1 1.0 1.0 1.0 1.0 1.0 1.0
2 1.0 1.0 1.0 1.0 1.0 1.0
3 1.0 1.0 1.0 1.0 1.0 1.0
4 1.0 1.0 1.0 1.0 1.0 1.0
5 1.0 1.0 1.0 1.0 1.0 1.0

cov(X,Y) = E( [X - E(X)] [Y - E(Y)] )

df.cov()
0 1 2 3 4 5
0 60.0 60.0 60.0 60.0 60.0 60.0
1 60.0 60.0 60.0 60.0 60.0 60.0
2 60.0 60.0 60.0 60.0 60.0 60.0
3 60.0 60.0 60.0 60.0 60.0 60.0
4 60.0 60.0 60.0 60.0 60.0 60.0
5 60.0 60.0 60.0 60.0 60.0 60.0
import matplotlib.pyplot as plt
%matplotlib inline

img = np.ones((500,500,3))
plt.imshow(img[:,:,0], cmap="gray")
<matplotlib.image.AxesImage at 0x7fd51a5e18d0>

png

a