主頁 > 後端開發 > 【Task01】Pandas學習打卡

【Task01】Pandas學習打卡

2020-12-18 11:31:27 後端開發

前言

在這里插入圖片描述

先看Pandas的百科介紹

pandas 是基于NumPy 的一種工具,該工具是為解決資料分析任務而創建的,Pandas
納入了大量庫和一些標準的資料模型,提供了高效地操作大型資料集所需的工具,pandas提供了大量能使我們快速便捷地處理資料的函式和方法,你很快就會發現,它是使Python成為強大而高效的資料分析環境的重要因素之一,

所以學好Python原生和Numpy對于學習Pandas很重要,在這一章節我們主要介紹Python和Numpy的一些比較重要的知識,本章學習的思維導圖如下:

在這里插入圖片描述

一、Python基礎

語法糖(Syntactic sugar),也譯為糖衣語法,是由英國計算機科學家彼得·約翰·蘭達(Peter J. Landin)發明的一個術語,指計算機語言中添加的某種語法,這種語法對語言的功能并沒有影響,但是更方便程式員使用,通常來說使用語法糖能夠增加程式的可讀性,從而減少程式代碼出錯的機會,

在Python原生中有很多好用的語法糖、物件和方法,在這里列舉幾個典型的并且常用的:

1.推導運算式與條件賦值

1)推導運算式

推導運算式是Python中常見的語法糖,在很多的資料處理場景中,我們可能會使用的到, 最常見的就是串列推導運算式,可以用來過濾、處理串列中的子項并輸出一個新的串列,除此之外還有幾個推導式也是非常好用的,

a.串列推導運算式

>>>a = [x for x in range(10)]
>>>print(a)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

b.生成器推導運算式

>>> in_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7]
>>> print('array before:', in_list)
>>> array = (i for i in in_list if i % 2 != 0) # 生成器推導運算式
>>> print('array after:', array)

c.集合推導運算式

>>> in_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7]
>>> print('array before:', in_list)
>>> array = {i for i in in_list if i % 2 != 0} # 集合推導運算式
>>> print('array after:', array)

d.字典推導運算式

>>> in_list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 8, 7]
>>> print('array before:', in_list)
>>> array = {i: i * 2 for i in in_list if i % 2 != 0}  # 字典推導運算式
>>> print('array after:', array)

其實,不止是節省代碼
耗時比較:
在這里插入圖片描述
另外,推導運算式中也可以使用多層回圈(大于等于2):

>>> a = ["第{}行{}列".format(i+1,j+1) for i in range(3) for j in range(3)]
>>> print(a)
['第1行1列', '第1行2列', '第1行3列', '第2行1列', '第2行2列', '第2行3列', '第3行1列', '第3行2列', '第3行3列']

2)條件賦值

條件賦值類似于三目運算子,由if判斷和賦值陳述句組成:

>>> a = b if a==b else c

上面的語法糖等價于:

>>> if b > c:
>>>     a = b
>>> else:
>>>     a = c

2.匿名函式與map方法

匿名函式的好處是省去了利用def去定義函式的步驟,壞處是不能重復使用:

>>> x = [(lambda x: x+2)(i) for i in range(10)]
>>> print(x)
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

map() 會根據提供的函式對指定序列做映射:

>>> x = list(map(lambda x:x+2,range(10)))
>>> print(x)
[2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

其中,函式需要的引數要放入map的引數中,

3.zip物件與enumerate方法

zip() 函式用于將可迭代的物件作為引數,將物件中對應的元素打包成一個個元組,然后回傳由這些元組組成的串列:

>>> a = 'xiao'
>>> b = 'ming'
>>> c = 'yuan'
>>> print(list(zip(a,b,c)))
[('x', 'm', 'y'), ('i', 'i', 'u'), ('a', 'n', 'a'), ('o', 'g', 'n')]

我們也可以使用zip去生成tuple和dict:

>>> print(tuple(zip(a,b,c)))
(('x', 'm', 'y'), ('i', 'i', 'u'), ('a', 'n', 'a'), ('o', 'g', 'n'))
>>> print(dict(zip(b,c)))
{'m': 'y', 'i': 'u', 'n': 'a', 'g': 'n'}

zip配合串列推導運算式使用:

>>> print(["第{}行{}列".format(i+1,j+1) for i,j in zip(range(3),range(3))])
['第1行1列', '第2行2列', '第3行3列']
  • 可理解為解壓:
>>> a = 'xiao'
>>> b = 'ming'
>>> c = 'yuan'
>>> zipped = list(zip(a,b,c))
>>> print(zipped)
[('x', 'm', 'y'), ('i', 'i', 'u'), ('a', 'n', 'a'), ('o', 'g', 'n')]
#復原方法一
>>> zipped_2 = list(zip(*zipped))
>>> print(zipped_2)
[('x', 'i', 'a', 'o'), ('m', 'i', 'n', 'g'), ('y', 'u', 'a', 'n')]
#復原方法二 
>>> original_1 = list(zip(zipped))
>>> print(original_1)
[(('x', 'm', 'y'),), (('i', 'i', 'u'),), (('a', 'n', 'a'),), (('o', 'g', 'n'),)]
#復原方法三
>>> original_2 = list(zip(zipped[0],zipped[1],zipped[2],zipped[3]))
>>> print(original_2)
[('x', 'i', 'a', 'o'), ('m', 'i', 'n', 'g'), ('y', 'u', 'a', 'n')]

方法二失敗的原因是zipped實際上是作為一個引數輸入,

對于方法一和方法三,我們可以看到,*和將zipped所有元素展開成多個引數是等價的,

enumerate:同時可呼叫索引和值

name = 'xiao'
for i,x in enumerate(name):
    print(str(i)+":"+x)
0:x
1:i
2:a
3:o

二、Numpy基礎

1.np陣列的構造

np陣列的構造
構造型別構造方法構造說明
依據現有資料構造array()會產生原資料的copy
asarray()當dtype變化時會產生原資料的copy
fromfunction()根據指定函式創建陣列
依據填充方式zeros()構造零陣列
empty()構造空陣列
eye()構造單位陣列
diag()構造對角陣列
full()構造常數陣列
利用陣列范圍來創建arange()回傳給定間隔內的均勻間隔的值
linspace()回傳指定間隔內的等間隔數字
logspace()回傳數以對數刻度均勻分布
結構陣列的創建np.array()+np.dtype()利用包含多個元組的串列來定義結構
np.array()+np.dtype()利用字典來定義結構
隨機生成random()利用隨機抽樣的概念生成陣列

1)依據現有資料構造

Ⅰ.array()方法

numpy.array(p_object, dtype=None, copy=True, order='K', subok=False, ndmin=0)
>>> datas = [x for x in range(10)]
>>> print(datas)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#通過array方法生成nd陣列
>>> nd_datas = np.array(datas)
>>> print(nd_datas,nd_datas.shape)
[0 1 2 3 4 5 6 7 8 9] (10,)
#改變原陣列
>>> datas[0] = 100
>>> #nd陣列并不會改變,說明產生的copy
>>> print(nd_datas,nd_datas.shape)
[0 1 2 3 4 5 6 7 8 9] (10,)

在這里我試圖用改變初始陣列的方式來判斷是否產生copy,此處也可以使用is進行比較,之后不再解釋,我們看到array默認產生一個copy,修改原陣列的資料并不會對生成的nd陣列產生影響,

Ⅱ.asarray()方法

numpy.asarray(a, dtype=None, order=None)
>>> datas = [x for x in range(10)]
>>> print(datas)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#通過asarray方法生成nd陣列
>>> nd_datas = np.asarray(datas)
>>> print(nd_datas,nd_datas.shape)
[0 1 2 3 4 5 6 7 8 9] (10,)
#改變原陣列
>>> datas[0] = 100
#nd陣列并不會改變,說明仍會產生的copy
>>> print(nd_datas,nd_datas.shape)
[0 1 2 3 4 5 6 7 8 9] (10,)

這樣看起來asarray()方法array()方法并沒有太大區別,我們且看下面這個例子:

>>> datas = [x for x in range(10)]
>>> nd_datas = np.array(datas)
>>> x = np.array(nd_datas)
>>> y = np.asarray(nd_datas)
>>> nd_datas[0] = 100
#后者沒有copy,說明仍會產生的copy
>>> print(x,y)
[0 1 2 3 4 5 6 7 8 9] [100   1   2   3   4   5   6   7   8   9]

當傳入資料是nd型別時,asarray()方法不會產生copy,而array()方法依然產生copy,

這是因為asarray()方法默認在不改變dtype時不copy,如:

>>> datas = [x for x in range(10)]
>>> nd_datas = np.array(datas,dtype='int16')
>>> x = np.asarray(nd_datas,dtype='int8')
>>> y = np.asarray(nd_datas,dtype='int16')
>>> z = np.asarray(nd_datas,dtype='int32')
>>> nd_datas[0] = 100
>>> print(x,y,z)
[0 1 2 3 4 5 6 7 8 9] [100   1   2   3   4   5   6   7   8   9] [0 1 2 3 4 5 6 7 8 9]

Ⅲ.fromfunction()方法

numpy.fromfunction(function, shape, *, dtype=<class 'float'>, **kwargs)

fromfunction()方法通過在每個坐標上執行一個函式來構造陣列,舉例:

>>> def f(x,y):
>>>     return 5*x+y
>>> data = np.fromfunction(f,(4,4))
>>> print(data)
[[ 0.  1.  2.  3.]
 [ 5.  6.  7.  8.]
 [10. 11. 12. 13.]
 [15. 16. 17. 18.]]

等價于:

>>> print(np.fromfunction(lambda i, j: 5*i+j, (4, 4)))
[[ 0.  1.  2.  3.]
 [ 5.  6.  7.  8.]
 [10. 11. 12. 13.]
 [15. 16. 17. 18.]]

2)依據填充方式構造

在機器學習任務中經常做的一件事就是初始化引數,需要用常數值或者隨機值來創建一個固定大小的矩陣,在這里介紹5中常用的矩陣填充方式:

Ⅰ.zeros()方法

numpy.zeros(shape, dtype=float, order='C')

zeros()方法用來回傳給定形狀和型別的零陣列:

#生成一個3*3的零陣列
>>> print(np.zeros([2,3]))
[[0. 0. 0.]
 [0. 0. 0.]]
numpy.zeros_like(a, dtype=None, order='K', subok=True, shape=None)

類似地,numpy中還有zeros_like()方法回傳與給定陣列形狀和型別相同的零陣列,舉例:

#創建一個2*3的二維陣列
>>> data = np.array([[1,2,3],[4,5,6]])
>>> print(np.zeros_like(data))
[[0 0 0]
 [0 0 0]]

Ⅱ.empty()方法

empty(shape, dtype=None, order='C')

empty()方法回傳一個空陣列,陣列元素為亂數:

>>> print(np.empty(5))
[2.12199584e-314 6.36598737e-314 1.06099790e-313 1.48539705e-313
 1.90979621e-313]
empty_like(prototype, dtype=None, order='K', subok=True, shape=None)

同樣地,也有empty_like()方法回傳與給定陣列具有相同形狀和型別的空陣列:

>>> data = np.array([[1,2,3],[4,5,6]])
>>> print(np.empty_like(data))
[[2964    0    0]
 [ 563    0  563]]

Ⅲ.eye()方法

numpy.eye(N, M=None, k=0, dtype=float, order='C')

eye()方法回傳一個對角線上為1,其它地方為零的單位陣列,可不是方陣:

#生成4*4的單位矩陣
>>> print(np.eye(4))
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]
#形狀為3*2
>>> print(np.eye(3,2))
[[1. 0.]
 [0. 1.]
 [0. 0.]]
#形狀為2*3
>>> print(np.eye(2,3))
[[1. 0. 0.]
 [0. 1. 0.]]

這里注意,如果給定一個兩個數并且不等,那么在生成的陣列中,會將從左上角第一個開始延展到邊界的路徑上設為1.

numpy.identity(n, dtype=None)

另外,numpy提供了只生成方的單位矩陣的identity()方法

>>> print(np.identity(4))
[[1. 0. 0. 0.]
 [0. 1. 0. 0.]
 [0. 0. 1. 0.]
 [0. 0. 0. 1.]]

Ⅳ.diag()方法

diag(v, k=0)

diag()方法用于提取對角線或構造對角陣列:

#提取對角線
>>> data = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> print(data)
[[1 2 3]
 [4 5 6]
 [7 8 9]]
#提取對角線
>>> print(np.diag(data))
[1 5 9]
#提取對角線 向右上偏移
>>> print(np.diag(data,k=1))
[2 6]
#提取對角線 向左下偏移
>>> print(np.diag(data,k=-1))
[4 8]

k代表偏移量,默認為0,右上方向為正,左下方向為負,

注:當引數是ndarray時,表示提取對角線;引數是list時,表示構建對角陣列:

>>> list = [x for x in range(1,6)]
>>> print(np.diag(list))
[[1 0 0 0 0]
 [0 2 0 0 0]
 [0 0 3 0 0]
 [0 0 0 4 0]
 [0 0 0 0 5]]

Ⅴ.full()方法

full()方法回傳一個由給定的值組成的常數陣列

numpy.full(shape, fill_value, dtype=None, order='C')
>>> print(np.full((3,2),7))
[[7 7]
 [7 7]
 [7 7]]
full_like(a, fill_value, dtype=None, order='K', subok=True, shape=None)

同樣地,我們也有full_like()方法,它的使用方式和之前的xx_like大致保持一致,回傳的是與給定陣列具有相同形狀和型別的常數陣列,并且由給定的值組成:

>>> data = np.array([[1,2,3],[4,5,6],[7,8,9]])
>>> print(np.full_like(data,7))
[[7 7 7]
 [7 7 7]
 [7 7 7]]

3)利用陣列范圍來創建

Ⅰ.arange()方法

numpy.arange([start,] stop[, step,], dtype=None)

arange()方法回傳給定間隔內的均勻間隔的值,舉例:

#指明終止位置(不包括),默認起點是0
>>> print(np.arange(5))
[0 1 2 3 4]
#無效
>>> print(np.arange(-5))
[]
#指明開始終止位置
>>> print(np.arange(1,5))
[1 2 3 4]
#指明開始終止位置和布長
>>> print(np.arange(1,5,2))
[1 3]

arange()方法的引數遵守左閉右開規則,并且默認start為0,

Ⅱ.linspace()方法

linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None, axis=0)

linspace()方法回傳指定間隔內的等間隔數字:

>>> print(np.linspace(1,5,9))
[1.  1.5 2.  2.5 3.  3.5 4.  4.5 5. ]

在這里插入圖片描述

arange()方法的引數遵守左閉右閉規則,并且須設定start和end,num默認為50,

Ⅲ.logspace()方法

logspace(start, stop, num=50, endpoint=True, base=10.0,dtype=None, axis=0)

logspace()方法回傳的數以對數刻度均勻分布:

>>> x = np.logspace(0, 1, 5)
>>> print(x)
[ 1.          1.77827941  3.16227766  5.62341325 10.        ]
>>> print(np.log10(x))
[0.   0.25 0.5  0.75 1.  ]
>>> print(np.linspace(0, 1, 5))
[0.   0.25 0.5  0.75 1.  ]

等價于先用linspace()方法,然后再對結果取以10為底的對數,

4)結構陣列的創建

Ⅰ.利用包含多個元組的串列來定義結構

結構陣列,首先需要定義結構,然后利用np.array()方法來創建陣列,其引數dtype為定義的結構,

>>> peopleType = np.dtype([('name', 'U20'), ('age', 'i1'), ('location', 'U20')])
>>> a = np.array([('xiaoA',20,'Beijing'),('xiaoB',20,'Shanghai'),('xiaoC',25,'Taiwan')],dtype=peopleType)
>>> print(a,type(a))
[('xiaoA', 20, 'Beijing') ('xiaoB', 20, 'Shanghai')
 ('xiaoC', 25, 'Taiwan')] <class 'numpy.ndarray'>
>>> print(a[0])
('xiaoA', 20, 'Beijing')
>>> print(a[0][0])
xiaoA

Ⅱ.利用字典來定義結構

現改為直接用字典方式訪問,只需對dtype進行處理,如:

>>> peopleType = np.dtype({ 'names': ['name', 'age', 'location'],'formats': ['U30', 'i8', 'U20']})
>>> a = np.array([('xiaoA',20,'Beijing'),('xiaoB',20,'Shanghai'),('xiaoC',25,'Taiwan')],dtype=peopleType)
>>> print(a,type(a))
[('xiaoA', 20, 'Beijing') ('xiaoB', 20, 'Shanghai')
 ('xiaoC', 25, 'Taiwan')] <class 'numpy.ndarray'>
#訪問所有名字
>>> print(a['name'])
['xiaoA' 'xiaoB' 'xiaoC']
>>> print(a[0])
('xiaoA', 20, 'Beijing')
#這兩種方式均可訪問屬性
>>> print(a[0][0])
xiaoA
>>> print(a[0]['name'])
xiaoA

5)隨機生成

簡單對numpy.random中隨機生成的方法做一個介紹:

方法名介紹
seed用于指定亂數生成時所用演算法開始的整數值
rand生成范圍0-1的隨機浮點數
randint生成指定范圍的整數
shuffle打亂資料
choice指定概率抽取元素
binomial實作二項分布
poisson實作泊松分布
hypergeometric實作超幾何分布
uniform實作均勻分布
normal實作正態分布
randn實作標準正態分布
exponential實作指數分布

這里只給出前五個方法的案例,其他例子請移步【Numpy-隨機抽樣】章節,這里不再展開:

【Numpy學習16】隨機抽樣

Ⅰ.seed()方法

numpy.random.seed(self, seed=None)

seed()方法用于指定亂數生成時所用演算法開始的整數值,規則:

  • 如果使用相同的seed( )值,則每次生成的隨即數都相同
  • 如果不設定這個值,則系統根據時間來自己選擇這個值,生成自己的種子,此時每次生成的亂數因時間差異而不同
  • 設定的seed()值僅一次有效
>>> np.random.seed(20201216)
>>> print(np.random.randint(1,10,5))
[1 7 8 9 5]
>>> np.random.seed(20201216)
>>> print(np.random.randint(1,10,5))
[1 7 8 9 5]

注意,設定的seed()值僅一次有效,例如:
在這里插入圖片描述

Ⅱ.rand()方法

numpy.random.rand(d0, d1, ..., dn)

random.rand()方法生成范圍0-1的隨機浮點數:

>>> print(np.random.rand(3,3))
[[0.30072091 0.01052971 0.06391355]
 [0.55119221 0.09069377 0.83557964]
 [0.85371122 0.91990132 0.27901161]]

Ⅲ.randint()方法

numpy.random.randint(low, high=None, size=None, dtype=int)

random.randint()方法生成指定范圍的整數:

>>> print(np.random.randint(1,10,(3,3)))
[[6 4 4]
 [5 9 7]
 [9 5 9]]

random.randint()方法遵循左閉右開原則,

Ⅳ.shuffle()方法

numpy.random.shuffle(x)

shuffle()方法用于打亂指定的陣列:

>>> x = np.arange(10)
>>> print(x)
>>> np.random.shuffle(x)
>>> print(x)
[0 1 2 3 4 5 6 7 8 9]
[4 0 8 7 6 9 2 5 1 3]
numpy.random.permutation(x)

同樣地,permutation()方法也可以打亂陣列,但它不會改變原來的陣列,只回傳打亂結果:

>>> x = np.arange(10)
>>> print(x)
[0 1 2 3 4 5 6 7 8 9]
>>> print(np.random.permutation(x))
[8 1 9 2 7 6 4 3 0 5]
>>> print(x)
[0 1 2 3 4 5 6 7 8 9]

我們可以看到,這種方式并沒有改變原始陣列,

另外,shuffle()方法只能對第一維度進行洗牌,如果想對第二維度洗牌,請使用:

numpy.random.Generator.shuffle(x, axis=0)

詳情參考中第三部分第2小節:

【Numpy學習16】隨機抽樣

Ⅴ.choice()方法

numpy.random.choice(a, size=None, replace=True, p=None)

choice()方法用于隨機從一維陣列從隨機抽取元素,默認概率相同:

>>> print(np.random.choice(10,10))
[1 4 8 9 9 3 7 7 3 0]
#不放回
>>> print(np.random.choice(10,10,replace=False))
[8 6 0 9 1 4 3 2 5 7]
#指定概率
>>> print(np.random.choice(10,10,p=[0.1,0,0,0,0,0,0,0,0,0.9]))
[9 9 9 9 9 9 9 0 9 0]

2.np陣列的變形與合并

1)翻轉陣列

函式描述
transpose對換陣列的維度
T和 self.transpose() 相同
rollaxis向后滾動指定的軸
swapaxes對換陣列的兩個軸

Ⅰ.transpose()方法

numpy.transpose(a, axes=None)

transpose()方法用于對換陣列的維度:

>>> a = np.arange(9).reshape(3,3)
>>> print(a)
[[0 1 2]
 [3 4 5]
 [6 7 8]]
>>> print(np.transpose(a))
[[0 3 6]
 [1 4 7]
 [2 5 8]]
#三維情況
>>> a = np.random.randint(0,10,(3,2,1))
#交換后面兩個維度
>>> print(np.transpose(a,(0,2,1)).shape)
(3, 1, 2)

Ⅱ.T方法

ndarray.T方法并沒有形參,只能用于轉置:

>>> a = np.arange(9).reshape(3,3)
>>> print(a.T)
[[0 3 6]
 [1 4 7]
 [2 5 8]]

2)陣列合并

陣列合并主要有下面幾種方法:

函式描述
concatenate連接沿現有軸的陣列序列
stack沿著新的軸加入一系列陣列,
hstack水平堆疊序列中的陣列(列方向)
vstack豎直堆疊序列中的陣列(行方向)

Ⅰ.concatenate()方法

numpy.concatenate((a1, a2, ...), axis=0, out=None)

concatenate()方法在不改變拼接原材料陣列的前提下,對指定的位置(axis)進行粘合:

>>> x = np.random.randint(0,10,(2,2))
>>> y = np.random.randint(0,10,(2,2))
#在第一維度進行拼接 下面三種方法是等價的
>>> print(np.concatenate([x,y]).shape)
(4, 2)
>>> print(np.r_[x,y].shape)
(4, 2)
>>> print(np.vstack([x,y]).shape)
(4, 2)
#在第二維度進行拼接 下面三種方法是等價的
>>> print(np.concatenate([x,y],axis=1).shape)
(2, 4)
>>> print(np.hstack([x,y]).shape)
(2, 4)
>>> print(np.c_[x,y].shape)
(2, 4)

concatenate()方法默認對第一維度進行粘合,且不會改變生成陣列的維度,

Ⅱ.stack()方法

numpy.stack(arrays, axis=0, out=None)
>>> x = np.random.randint(0,10,(3,4))
>>> y = np.random.randint(0,10,(3,4))
>>> print(np.stack([x,y]).shape)
(2, 3, 4)
>>> print(np.stack([x,y],axis=1).shape)
(3, 2, 4)
>>> print(np.stack([x,y],axis=2).shape)
(3, 4, 2)

concatenate方法不同的是,stack方法生成的陣列比原始陣列維度多1,且多的維度的長度等于原始陣列的長度:

  • 兩個shape為(3,3)的原始陣列,axis=0,結果陣列shape為(2,3,3)
  • 兩個shape為(3,3)的原始陣列,axis=1,結果陣列shape為(3,2,3)
  • 兩個shape為(3,3)的原始陣列,axis=2,結果陣列shape為(3,3,2)

且位置正是axis,

3)維度變換

在numpy中,修改陣列維度的方法有如下幾種:

函式描述
reshape不改變資料的條件下修改形狀
flat陣列元素迭代器
flatten回傳一份陣列拷貝,對拷貝所做的修改不會影響原始陣列
ravel回傳展開陣列

Ⅰ.reshape()方法

numpy.reshape(a, newshape, order='C')

reshape()方法可以在不改變資料的條件下修改形狀:

>>> a = np.arange(12)
>>> print(a)
[ 0  1  2  3  4  5  6  7  8  9 10 11]
>>> print(a.reshape(3,4).shape)
(3, 4)
>>> print(a.reshape(2,6).shape)
(2, 6)
# -1表示自動填充,reshape引數最多只允許有一個-1存在
>>> print(a.reshape(2,-1).shape)
(2, 6)

我們可以看到,reshape(2,6)和reshape(2,-1)的輸出結果是一樣的,這是因為-1進行了自動補全,即用總數除其他維度的維數,

Ⅱ.flatten()方法

ndarray.flatten(order='C')

flatten()方法回傳原始陣列展開后的拷貝,對拷貝所做的修改不會影響原始陣列:

>>> a = np.arange(6).reshape(2,3)
>>> b = a.flatten()
>>> b[0] = 100
>>> print(b)
[100   1   2   3   4   5]
>>> print(a)
[[0 1 2]
 [3 4 5]]

注:在這里只介紹陣列操作的部分方法,其他方法請參考:

【Numpy學習09】陣列操作

3.np陣列的切片與索引

1)整數索引

>>> a = np.random.randint(0,10,5)
>>> print(a,a[2])
[2 7 3 6 6] 3
>>> b = np.random.randint(0,10,(5,5))
>>> print(b,b[3][1],b[3,1])
[[3 7 0 7 9]
 [1 6 9 3 1]
 [2 7 5 0 7]
 [6 2 6 1 0]
 [5 5 6 8 1]] 2 2
>>> c = np.random.randint(0,10,(3,3,3))
>>> print(c,c[0][0][0],c[0,0,0])
[[[6 1 5]
  [9 5 9]
  [2 3 5]]

 [[1 1 5]
  [2 1 5]
  [1 5 4]]

 [[3 5 9]
  [8 9 6]
  [7 3 3]]] 6 6

2)切片索引

#二維陣列
>>> a = np.random.randint(0,10,(5,5))
>>> print(a)
[[7 7 9 8 0]
 [7 9 9 9 9]
 [2 1 4 7 7]
 [4 9 7 3 8]
 [2 1 8 2 8]]
#第2行與第3、4列交匯的資料
>>> print(a[1,2:4])
[9 9]
#第2列與第3、4行交匯的資料
>>> print(a[2:4,1])
[1 9]
#第3、4行與第3、4列交匯的資料
>>> print(a[2:4,2:4])
[[4 7]
 [7 3]]
#從第一行開始以2為步長的行與從第一行開始以2為步長的列交匯的資料
>>> print(a[::2,::2])
[[7 9 0]
 [2 4 7]
 [2 8 8]]
#去掉最后一列
>>> print(a[...,:-1])
[[7 7 9 8]
 [7 9 9 9]
 [2 1 4 7]
 [4 9 7 3]
 [2 1 8 2]]
>>> a = np.arange(9).reshape(3,3)
>>> print(a)
[[0 1 2]
 [3 4 5]
 [6 7 8]]
>>> print(a[np.ix_([0,2],[0,2])])
[[0 2]
 [6 8]]

np.ix_()方法完美解決了任何幾行和幾列的交集問題,

3)整數陣列索引

>>> a = np.random.randint(0,10,(5,5))
>>> print(a)
[[6 2 9 7 2]
 [8 5 4 5 9]
 [1 4 3 3 9
 [9 8 0 8 8]
 [7 1 6 5 2]]
>>> s = [0,2,3]
>>> p = [1,2,4]
>>> print(a[s,p])
[2 3 8]

4)布爾索引

#控制型別,找到不是nan的資料
>>> c = np.array([np.nan,9,8,7,np.nan,6,5])
>>> d = np.logical_not(np.isnan(c))
>>> print(d)
[False  True  True  True False  True  True]
>>> print(c[d])
[9. 8. 7. 6. 5.]

4.常用函式

1)where

numpy.where(condition[, x, y])

numpy.where() 方法回傳輸入陣列中滿足給定條件的元素的索引:

#一維情況
>>> a = np.random.randint(0,10,5)
>>> print(a)
[0 6 1 0 8]
>>> print(np.where(a>5))
(array([1, 4], dtype=int64),)
#二維情況
>>> a = np.random.randint(0,10,(3,3))
>>> print(a)
[[7 6 2]
 [2 7 7]
 [4 9 9]]
>>> print(np.where(a>5))
(array([0, 0, 1, 1, 2, 2], dtype=int64), array([0, 1, 1, 2, 1, 2], dtype=int64))

在二維情況下,回傳的陣列分別是x和y的坐標集合,如上面的例子,分別是(0,0)、(0,1)…(2,2),不要混淆,

numpy.where() 方法還有另外一種用法,回傳的是與原始數字相同shape的陣列并且改變其中的資料,但并不影響原始陣列:

>>> a = np.random.randint(0,10,5)
>>> print(a)
[6 6 4 5 9]
>>> print(np.where(a>5,0,a))
[0 0 4 5 0]
>>> print(a)
[6 6 4 5 9]

2)nonzero,argmax,argmin

Ⅰ.nonzero()方法

numpy.nonzero(a)

numpy.nonzero() 方法回傳輸入陣列中非零元素的索引:

#一維
>>> a = np.random.randint(-1,2,10)
>>> print(a)
[ 0  1  1  0  1  0  0  0  0 -1]
>>> print(np.nonzero(a))
(array([1, 2, 4, 9], dtype=int64),)
#二維
>>> a = np.random.randint(-1,2,(3,3))
>>> print(a)
[[ 0  0  1]
 [ 1 -1 -1]
 [ 0  0  1]]
>>> print(np.nonzero(a))
(array([0, 1, 1, 1, 2], dtype=int64), array([2, 0, 1, 2, 2], dtype=int64))
#回傳所有非0值
>>> print(a[np.nonzero(a)])
[ 1  1 -1 -1  1]

numpy.nonzero() 方法的一些規則:

  • 只有a中非零元素才會有索引值,那些零值元素沒有索引值
  • 回傳一個長度為a.ndim的元組(tuple),元組的每個元素都是一個整數陣列(array)
  • 每一個array均是從一個維度上來描述其索引值,比如,如果a是一個二維陣列,則tuple包含兩個array,第一個array從行維度來描述索引值;第二個array從列維度來描述索引值,注意,一位陣列回傳的結果外層有一層元組包裹
  • 通過a[nonzero(a)]得到所有a中的非零值

Ⅱ.argmax()和argmin()方法

numpy.argmax(a, axis=None, out=None)
numpy.argmin(a, axis=None, out=None)

由于argmax()和argmin()方法用法相似,這里只介紹前者,argmax()方法回傳的是根據axis=n為參考,沿著第n維度的最大值的索引,如果不設定axis,那么原陣列會被平鋪:

>>> a = np.random.randint(0,10,5)
>>> print(a)
[4 2 1 5 0]
>>> print(np.argmax(a))
3

如果有超過1個最大值,會回傳第一個:

在這里插入圖片描述

3)any,all

numpy.all(a, axis=None, out=None, keepdims=<no value>)
numpy.any(a, axis=None, out=None, keepdims=<no value>)

真值測驗包含np.all()np.any()兩種方法:

  • np.all()判斷是否全為真:如果是就回傳True;否則回傳False,
  • np.any()判斷是否至少有一個為真:如果有就回傳True;否則回傳False,

舉例:

>>> a = np.random.randint(0,5,5)
>>> print(a)
[0 0 0 4 0]
>>> print(np.all(a<5))
True
>>> print(np.any(a<0))
False
>>> print(np.all([2,np.nan]))
True

注意對np.nan的判斷,實際上它是一個numpy.float64物件,真值判斷時它為True,

4)cumprod,cumsum,diff

numpy.cumprod(a, axis=None, dtype=None, out=None)
numpy.cumsum(a, axis=None, dtype=None, out=None)
numpy.diff(a, n=1, axis=-1, prepend=<no value>, append=<no value>)

這三個方法分別代表累積、累加、和相鄰差:

>>> a = np.arange(1,10).reshape(3,3)
>>> print(a)
[[1 2 3]
 [4 5 6]
 [7 8 9]]
>>> print(np.cumprod(a))
[     1      2      6     24    120    720   5040  40320 362880]
>>> print(np.cumsum(a))
[ 1  3  6 10 15 21 28 36 45]
>>> print(np.diff(a))
[[1 1]
 [1 1]
 [1 1]]

注意,這里diff()方法的axis默認為-1,對于上面的例子,即求相鄰列的差,

5)統計函式

Nump中的統計函式如下:
在這里插入圖片描述

這里只舉幾個常用的例子:

>>> nums = np.array([[10, 7, 4],[3, 2, 1]])
#中位數
>>> print(np.median(nums))
3.5
#70分位數
>>> print(np.percentile(nums,70))
5.5
#均值
>>> print(np.mean(nums))
4.5
#極差
>>> print(np.ptp(nums))
9
#方差
>>> print(np.var(nums))
9.583333333333334
#標準差
>>> print(np.std(nums))
3.095695936834452

5.廣播機制

當運算中的 2 個陣列的形狀不同時,numpy 將自動觸發廣播機制,

廣播的規則:

  • 讓所有輸入陣列都向其中形狀最長的陣列看齊,形狀中不足的部分都通過在前面加 1 補齊,
  • 輸出陣列的形狀是輸入陣列形狀的各個維度上的最大值,
  • 如果輸入陣列的某個維度和輸出陣列的對應維度的長度相同或者其長度為 1 時,這個陣列能夠用來計算,否則出錯,
  • 當輸入陣列的某個維度的長度為 1 時,沿著此維度運算時都用此維度上的第一組值,

簡單概括就是,如果shape不匹配,必須滿足情況1或情況2才能滿足廣播,超過二維時可以是截面圖:
在這里插入圖片描述

舉例:

>>> a = np.random.randint(0,10,(2,1))
>>> b = np.random.randint(0,10,(1,3))
>>> print((a+b).shape)
(2, 3)

兩個一維陣列必須保證長度相同,否則:
在這里插入圖片描述

其中一個為一維時,另一個陣列最后一個維度的維數須為1或者等于一維陣列的長度,否則:
在這里插入圖片描述

6.向量與矩陣的計算

1)向量內積 dot

numpy.dot(a, b, out=None)

Ⅰ.一維向量的積

在這里插入圖片描述

當a和b均為一維時,dot()方法即為求2個陣列對應的乘積:1*3+2*4 = 11
,注意此時a和b的長度需要保持一致,否則會報錯:

在這里插入圖片描述

Ⅱ.shape分別為(a,m)和(m,b)的矩陣之積

在這里插入圖片描述

上面的例子就是正常的矩陣乘法,我們也可以用np.matmul()方法實作

但需要保證a最后維度的維數和b第一維度的維數保持一致,否則會報錯:

在這里插入圖片描述

Ⅲ.矩陣與標量之積

在這里插入圖片描述

此時,可以直接用‘*’代替np.dot()方法

Ⅳ.第二個引數是一維向量的情況

在這里插入圖片描述

我們可以看到,此時ndarray在一維時的表達解答了我在前面學習程序中的思考,為什么一維ndarray變數的shape是(n,)而不是(,n),最后的結果依然保持一維,

此時需要滿足矩陣最后維度的維數等于向量的長度,否則依然會報錯:

在這里插入圖片描述

注:對于線性代數中的n維行向量,numpy表示為形如(n,)的一位陣列;對于線性代數中的n維列向量,numpy表示為行如(n,1)的二維陣列,

2)向量范數和矩陣范數

在這里插入圖片描述

在這里插入圖片描述

3)矩陣乘法

在這里插入圖片描述

此種情況下,與np.dot()方法保持一致,

三、練習

Ex1:利用串列推導式寫矩陣乘法

>>> a = np.array([sum(M1[i,k]*M2[k,j] for k in range(p)) for i in range(m) for j in range(n)]).reshape(m,n)
>>> print(a)
[[1.21998497 1.22514323 0.96636003 0.7386822 ]
 [1.01499004 1.08397318 0.77515486 0.53678796]]
>>> b = M1@M2
>>> print(b)
[[1.21998497 1.22514323 0.96636003 0.7386822 ]
 [1.01499004 1.08397318 0.77515486 0.53678796]]
>>> print(np.allclose(a,b))
True

思路:

在這里插入圖片描述

先求出m,p,n這兩個矩陣長寬指標,然后最外層的兩層回圈分別是m和n,最內層的回圈是計算單個元素結果,后面要加一個reshape()方法去固定生成矩陣的維數,

Ex2:更新矩陣

>>> A = np.arange(1,10).reshape(3,-1)
>>> B = A*(1/A).sum(1).reshape(-1,1)
>>> print(B)
[[1.83333333 3.66666667 5.5       ]
 [2.46666667 3.08333333 3.7       ]
 [2.65277778 3.03174603 3.41071429]]

在這里插入圖片描述

Ex3:卡方統計量

>>> np.random.seed(20201216)
>>> def getB(A):
>>>     #shape:5,
>>>     a = A.sum(axis=0)
>>>     #shape:8,
>>>     b = A.sum(axis=1)
>>>     total = A.sum()
>>>     #生成shape滿足(8,5) 所以要把b提升維度 再利用廣播特性
>>>     B = a*b.reshape(-1,1)/total
>>>     return B
>>> A = np.random.randint(10, 20, (8, 5))
>>> B = getB(A)
>>> result = np.power(A-B,2)/B
>>> print(result.sum())
17.490048845986898

Ex4:改進矩陣計算的性能

>>> np.random.seed(20201216)
>>> m, n, p = 100, 80, 50
>>> B = np.random.randint(0, 2, (m, p))
>>> U = np.random.randint(0, 2, (p, n))
>>> Z = np.random.randint(0, 2, (m, n))
>>> res = [(np.power(B[i]-U[...,j],2).sum())*Z[i,j] for i in range(m) for j in range(n)]
print(sum(res))
102517

方法一:利用串列推導運算式改進性能:

在這里插入圖片描述

方法二:利用Numpy特性—向量化與廣播:

R的左側結果是一個m * n的矩陣,暫定為A,右側Z也是一個m * n的矩陣,重點是將左側矩陣用代碼表示出來,我嘗試用一種簡單清晰的方式解釋如何用代碼表示:

第一步,求A的第一個元素:

在這里插入圖片描述

由公式可知在固定i和j時,就是求一個常量,以i=0,j=0為例:

#i鎖定為0 j鎖定為0 生成1個item
>>> b = B[0]
>>> print(b.shape)
(50,)
>>> u = U[...,0]
>>> print(u.shape)
(50,)
#這里利用Numpy向量化進行展開,實際上是陣列中相對應位置的每一個元素的平方,而不要理解成矩陣乘法
>>> result = b**2+u**2-2*b*u
>>> print(result.shape)
(50,)
>>> print(result.sum())
24

這里的b和u都是一維陣列,長度都為50(也就是p),而b**2的shape依然與b保持一致,這里利用了Numpy中的向量化特性,意思是對b的每一個元素求平方,

第二步,求A的第一行元素:

在這里插入圖片描述
由公式可知在固定i時,就是在第一步的基礎上重復n次,以i=0為例:

>>> b = B[0]
>>> print(b.shape)
(50,)
>>> b = b.reshape(-1,1)
>>> result = (b**2+U**2-2*b*U).sum(axis=0)
>>> print(result.shape)
(80,)

這里解釋一下為什么要對b進行reshape操作,在第一步中b和u都是一維陣列且長度相同,所以可以直接進行數學運算,但在此處U的shape為(p,n),根據廣播的法則b * U會出錯,此時需要對b進行升維,即變為(p,1),這樣b * N的結果即為(p,n),

在這一步,我們最終得到的結果是一個長度為n的一位陣列,它代表了A矩陣的第一行,

第三步,求整個A:

在這里插入圖片描述

由公式可知,這一步就是在第二步的基礎上重復m次:

>>> print(((B**2).sum(axis=1,keepdims=True) + (U**2).sum(axis=0) - 2*B@U).shape)
(100, 80)

讓我們來依次解釋,從結果反推我們不難得知最后的結果需要滿足shape為(m,n),B@U結果的shape為(m,n),而B ** 2的shape為(m,p),所以要對最后一個維度進行求和并且保留當前維度,同理U**2的shape為(p,n),所以要對第一個維度進行求和,這樣就可以保證可以成功生成m*n的矩陣,

從另一個角度,對于B來說,單獨一行的資訊屬于一個整體,所以需要將它們進行按列求和匯總;同理,對于U來說,單獨一列的資訊屬于一個整體,所以需要將它們按行求和匯總,并且對于B來說,需要滿足廣播條件,所以B要保持自己的維度屬性,

時耗查看:

在這里插入圖片描述

對比方法一幾乎節省了99%的時間,原因是充分利用了Numpy的向量化和廣播特性,

Ex5:連續整數的最大長度

>>> def func(data):
>>>     #在頭尾插入一個標志變數
>>>     data.insert(0,data[0]-2)
>>>     data.insert(len(data),data[-1]+2)
>>>     return np.diff(np.nonzero(np.diff(data)!=1)).max()
>>> print(func([1,2,5,6,7]))
3
>>> print(func([3,2,1,2,3,4,6]))
4

思路:先在頭尾插入標志變數,防止出現0,1,2,3,5或者0,2,3,4,5這樣左或右存在連續邊界值,第一次diff計算的是原陣列相鄰差值,然后求不連續的坐標,之后再使用第二次diff求得相鄰兩個不連續坐標的差值,然后求最大值即為所求,

自己的做法:

>>> def func(x):
>>>     a = np.diff(x)
>>>     result = 0
>>>     temp = 0
>>>     for item in a:
>>>         if item == 1:
>>>             temp += 1
>>>         else:
>>>             result = temp if temp > result else result
>>>             temp = 0
>>>     result = temp if temp > result else result
>>>     return result+1
>>> print(func([1,2,5,6,7]))
3
>>> print(func([3,2,1,2,3,4,6]))
4

用一次diff方法生成a,遍歷一次a,得到結果,時間復雜度O(n),空間復雜度O(1),

參考文獻

#Python語法糖系列

1、https://blog.csdn.net/five3/article/details/83474633

#Python菜鳥教程

2、https://www.runoob.com/python/python-tutorial.html

#Numpy系列學習手冊

3、Numpy入門系列學習手冊

陣列的創建

陣列操作

索引與切片

向量化和廣播

數學函式

邏輯函式

排序,搜索和計數

隨機抽樣

統計相關

線性代數

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/236593.html

標籤:python

上一篇:Python搬磚之旅(2nd day):基礎語法、變數、基礎資料型別、運算子、輸入輸出

下一篇:SimpleGUI制作彈框(Python)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more