【數據分析“三劍客”】—— Pandas

Pandas

  • Pandas 是基于NumPy的一種工具,該工具是為解決數據分析任務而創建的, Pandas提供了大量能使我們快速便捷地處理數據的函數和方法。
  • Pandas與出色的 Jupyter工具包和其他庫相結合,Python中用于進行數據分析的環境在性能、生產率和協作能力方面都是卓越的。
  • Pandas的主要數據結構是 **Series(**一維數據)與 **DataFrame **(二維數據),Pandas的Series和DataFrame在數據分析領域引入了更多高級功能和更豐富的數據結構,特別是需要處理結構化數據、缺失值、時間序列以及進行復雜統計分析時。

導包

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

Series

Series是一種類似于一維數組的對象,由下面兩個部分組成:

  • values:一組數據(ndarray類型)
  • index:相關的數據索引標簽

Series可以看作是ndarray數組的升級版,因為它不僅存儲數據,還存儲了數據的索引,這樣就可以通過標簽來訪問數據,而不僅僅是基于位置的訪問。

Series的創建

兩種創建方式:

由列表或NumPy數組創建

list1 = [11, 22, 33, 44]
n = np.array(list1)
type(n)  # numpy.ndarrays = Series(n)
display(type(s))  # pandas.core.series.Series

Series屬性: index和values

# values屬性
s.values  # array([11, 22, 33, 44])s.index
# RangeIndex(start=0, stop=4, step=1)
list(s.index)# 修改索引
s.index = list("abcd")
s.index = ["魯班", "李白", "諸葛亮", "張飛"]
display(s)# 通過索引取值
s.魯班, s['魯班']# 通過索引修改值
s['魯班'] = 100

通過字典創建

d = {'a': 11,'b': 22,'c': 33,'d': 44
}
s = Series(d)
s.index = list("ABCD")
display(s)d = {'a': np.random.randint(0, 10, size=(2,3)),'b': np.random.randint(0, 10, size=(2,3)),'c': np.random.randint(0, 10, size=(2,3)),'d': np.random.randint(0, 10, size=(2,3))
}
s = Series(d)
display(s)# 創建時同時設置索引
s = Series([1,2,3], index=["張三", '李四', '王五'])
display(s)

Series的索引

可以使用中括號取單個索引(此時返回的是元素類型),或者中括號里一個列表取多個索引(此時返回的仍然是一個Series類型)。分為顯示索引和隱式索引:

(1) 顯式索引:
  • 使用index中的元素作為索引值
  • 使用.loc[]

注意,此時是閉區間

s = Series({'語文': 150, "數學": 100, "英語": 120, "Python": 99})# 顯式索引:使用索引名字
s['語文']  # int類型
s[['語文', "Python", "數學"]]  # Series類型
s[['語文']]  # Series類型# .loc[ ]
s.loc['語文']
s.loc[['語文', "Python", "數學"]] 
s.loc[['語文']]
(2) 隱式索引:
  • 使用整數作為索引值
  • 使用.iloc[](推薦)integer location 整數位置

注意,此時是半開區間

s = Series({'語文': 150, "數學": 100, "英語": 120, "Python": 99})# 隱式索引: 使用數字下標
s[0]
s[[0, 2, 1]]
s[[0]]# iloc[ ]
s.iloc[0]
s.iloc[[0, 2, 1]]
s.iloc[[0]]

Series的切片

  • Series一維數組切片
s = Series({'語文': 150, "數學": 100, "英語": 120, "Python": 99, "Numpy": 66, "Pandas": 199})# Series是一維數組# 顯式切片: 閉區間
s["數學": "Python"]
s.loc["數學": "Python"]# 隱式切片 : 左閉右開
s[1: 4]
s.iloc[1: 4]

Series的屬性和方法

  • shape 形狀
  • size 大小
  • index 索引
  • values 值
  • dtype 元素類型
  • name 名字
s.shape  # 形狀
s.size  # 元素個數
s.index  # 索引
s.values  # 值
s.dtype  # 元素類型s = Series([11, 22, 33], name="年齡")
s.name  # Series名字

查看首尾數據

  • head() 查看前幾條數據,默認5條
  • tail() 查看后幾條數據,默認5
# 查看前幾條數據,默認5條
head() 
s.head()  
s.head(2)# 查看后幾條數據,默認5
tail() 
s.tail()
s.tail(2)

檢測缺失數據

  • pd.isnull()
  • pd.notnull()
  • isnull()
  • notnull()
# s.isnul()
pd.isnull(s)# s.notnull()
pd.notnull(s)# 可以通過True,Flase過濾數據# 保留不為空的數據
s[ pd.notnull(s) ]

Series的運算

(1) 適用于NumPy的數乘運算也適用于Series
s = Series(np.random.randint(10, 100, size=10))s + 100
s - 100
s * 100
s / 100
s // 10
s ** 2
(2) Series之間的運算
  • 在運算中自動對齊索引的數據
  • 如果索引不對應,則補NaN
  • Series沒有廣播機制
s1 = Series(np.random.randint(10, 100, size=3))
s2 = Series(np.random.randint(10, 100, size=4))
display(s1 + s2)# Numpy中有廣播機制
n1 = np.array(np.random.randint(1, 10, size=(1, 3)))
n2 = np.array(np.random.randint(1, 10, size=(3, 1)))
display(n1 + n2)
  • 注意:要想保留所有的index,類似于sql的全連接,保存兩個運算對象的所有index,則需要使用.add()函數,使用NaN補齊運算結果
s1.add(s2, fill_value=100)

DataFrame

DataFrame是一個二維表格型的數據結構,可以看做是由Series組成的字典。DataFrame由按一定順序排列的多列數據組成。設計初衷是將Series的使用場景從一維拓展到多維。DataFrame既有行索引,也有列索引。

  • 行索引:index
  • 列索引:columns
  • 值:values

DataFrame的創建

最常用的方法是傳遞一個字典來創建。DataFrame以字典的鍵作為每一列的索引名稱,以字典的值(一個數組)作為每一列的內容。此外,DataFrame會自動加上每一行的索引,行索引為從0開始的自然數。

同Series一樣,若傳入的列與字典的鍵不匹配,則相應的值為NaN

d = {'name' : ["魯班", '陳咬金', "豬八戒"],'age' : [7, 9, 8],'sex': ['男', '女', '男']
}
df = DataFrame(d)

在創建時,指定數據、行索引和列索引

df = DataFrame(data=np.random.randint(0, 100, size=(4, 6)),index=['小明', "小紅", '小綠', '小黃'],columns=['語文', '數學', '英語', 'Python', 'Numpy', 'Pandas']
)
df

DataFrame屬性和方法

  • values 值
  • columns 列索引
  • index 行索引
  • shape 形狀
  • head() 查看前幾行數據
  • tail() 查看后幾行數據
# 創建DataFrame
df = DataFrame(d, index=["第一行", "第二行", "第三行"])df.values  # 值,二維ndarray數組
df.columns   # 列索引
df.index  # 行索引
df.shape  # 形狀# 查看首尾數據
df.head(2)
df.tail(2)

DataFrame的索引

對列進行索引

  • 通過類似字典的方式
  • 通過屬性的方式

可以將DataFrame的列獲取為一個Series。返回的Series擁有原DataFrame相同的索引,且name屬性也已經設置好了,就是相應的列名。

df = DataFrame(data=np.random.randint(0, 100, size=(4, 6)),index=['小明', "小紅", '小綠', '小黃'],columns=['語文', '數學', '英語', 'Python', 'Numpy', 'Pandas']
)df.語文
df['語文']  # Seriesdf[['語文', 'Python']]  # DataFrame
df[['語文']]

對行進行索引

  • 使用.loc[ ]加index來進行行索引
  • 使用.iloc[ ]加整數來進行行索引

同樣返回一個Series,index為原來的columns。

df = DataFrame(data=np.random.randint(0, 100, size=(4, 6)),index=['小明', "小紅", '小綠', '小黃'],columns=['語文', '數學', '英語', 'Python', 'Numpy', 'Pandas']
)# DataFrame默認取列索引
df.loc['小明']  # Series
df.iloc[0]df.loc[['小明', '小綠']]  # DataFrame
df.loc[['小明']] 
df.iloc[[0, 2]]  # DataFrame
df.iloc[[0]]

對元素索引的方法

df = DataFrame(data=np.random.randint(0, 100, size=(4, 6)),index=['小明', "小紅", '小綠', '小黃'],columns=['語文', '數學', '英語', 'Python', 'Numpy', 'Pandas']
)# 先取列,再取行
df['語文'][1]
df['語文']['小明']# 先取行,再取列
df.iloc[1]['語文']  # 列索引的符號不可以用整數代替
# df.loc['小明', '語文']  

DataFrame的切片

【注意】 直接用中括號時:

  • 索引表示的是列索引
  • 切片表示的是行切片
df = DataFrame(data=np.random.randint(0, 100, size=(4, 6)),index=['小明', "小紅", '小綠', '小黃'],columns=['語文', '數學', '英語', 'Python', 'Numpy', 'Pandas']
)# 索引: 優先使用列索引, 先取行就需要寫loc或iloc
# 切片: 優先按行切片, 和Numpy操作類似# 行: 行名, 行數字索引
# 列: 列名# 行切片
df[1 : 3]  # 左閉右開
df['小明' : "小綠"]  # 閉區間df.iloc[1 : 3]
df.loc['小明' : "小綠"]# 列切片: 需要使用loc或iloc
df.iloc[:, 1:3]
df.loc[:, "數學": "Python"]df.loc["小明":"小綠", "數學":"Python"]
df.iloc[:3, 1:4]

DataFrame的運算

DataFrame之間的運算
  • 在運算中自動對齊索引的數據
  • 如果索引不對應,則補NaN
  • DataFrame沒有廣播機制
# 創建DataFrame df1 不同人員的各科目成績,月考一
df1 = DataFrame(data={'Python': [100, 90, 80], 'Java': [80, 70, 60], 'PHP': [60, 50, 40]},index=['張飛', "呂布", '關羽']
)# 創建DataFrame df2 不同人員的各科目成績,月考二
df2 = DataFrame(data={'Python': [100, 90, 80, 70], 'Java': [80, 70, 60, 50], 'PHP': [60, 50, 40, 30], 'Go': [40, 30, 20, 10]},index=['張飛', "呂布", '關羽', "劉備"]
)# DataFrame和數的運算
display(df1 + 100)# DataFrame之間的運算
display(df1 + df2)# 自動填充, 再相加
df1.add(df2, fill_value=1000)
Series與DataFrame之間的運算
  • 使用Python操作符:以行為單位操作(參數必須是行),對所有行都有效。(類似于numpy中二維數組與一維數組的運算,但可能出現NaN)

  • 使用pandas操作函數:

    axis=0:以列為單位操作(參數必須是列),對所有列都有效。
    axis=1:以行為單位操作(參數必須是行),對所有行都有效。

# 創建DataFrame df1 不同人員的各科目成績,月考一
df1 = DataFrame(data={'Python': [100, 90, 80], 'Java': [80, 70, 60], 'PHP': [60, 50, 40]},index=['張飛', "呂布", '關羽']
)s = Series([100, 10, 1], index=df1.columns)# 直接相加
df1 + s# 使用add函數
df1.add(s)
df1.add(s, axis='columns')  # 列
df1.add(s, axis=1)  # 第二個維度s = Series([100, 10, 1], index=df1.index)
df1.add(s, axis='index')  # 行
df1.add(s, axis=0)  # 行

Pandas層次化索引

創建多層行索引

隱式構造

  • 最常見的方法是給DataFrame構造函數的index參數傳遞兩個或更多的數組
data = np.random.randint(0, 100, size=(6, 6))index = [['1班', '1班', '1班', '2班', '2班', '2班'],['張三', '李四', '王五', '趙六', '田七', '孫八']
]columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['語文', '數學', '英語', '語文', '數學', '英語']
]df = pd.DataFrame(data=data, index=index, columns=columns)
df
  • Series也可以創建多層索引
data = np.random.randint(0, 100, size=6)index = [['1班', '1班', '1班', '2班', '2班', '2班'],['張三', '李四', '王五', '趙六', '田七', '孫八']
]s  = pd.Series(data=data, index=index)
s

顯示構造pd.MultiIndex

  • 使用數組
data = np.random.randint(0, 100, size=(6, 6))index = pd.MultiIndex.from_arrays( [['1班', '1班', '1班', '2班', '2班', '2班'],['張三', '李四', '王五', '趙六', '田七', '孫八']
] )columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['語文', '數學', '英語', '語文', '數學', '英語']
]df = pd.DataFrame(data=data, index=index, columns=columns)
df
  • 使用tuple
data = np.random.randint(0, 100, size=(6, 6))index = pd.MultiIndex.from_tuples( (('1班', '張三'), ('1班', '李四'), ('1班', '王五'), ('2班', '趙六'), ('2班', '田七'), ('2班', '孫八'), )
)columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['語文', '數學', '英語', '語文', '數學', '英語']
]df = pd.DataFrame(data=data, index=index, columns=columns)
df
  • 使用product
data = np.random.randint(0, 100, size=(6, 6))# 笛卡爾積:{a, b} {c, d} => {a,c}, {a,d}, {b,c}, {b,d}
index = pd.MultiIndex.from_product( [['1班',  '2班'],['張三', '李四', '王五']]
)columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['語文', '數學', '英語', '語文', '數學', '英語']
]df = pd.DataFrame(data=data, index=index, columns=columns)
df

創建多層列索引(同行索引)

除了行索引index,列索引columns也能用同樣的方法創建多層索引

多層索引對象的索引與切片操作

Series的操作【重要】

對于Series來說,直接中括號[]與使用.loc()完全一樣

# (1) 索引
data = np.random.randint(0, 100, size=6)index = [['1班', '1班', '1班', '2班', '2班', '2班'],['張三', '李四', '王五', '趙六', '田七', '孫八']
]s  = pd.Series(data=data, index=index)
s# 顯式索引
s['1班']
s.loc['1班']s.loc[['1班']]
s.loc[['1班', '2班']]s['1班']['張三']
s.loc['1班']['張三']
s.loc['1班','張三']
s['1班', '張三']#隱式索引
s[1]
s.iloc[1]
s.iloc[[3, 2]]# (2) 切片
# 顯式切片
s['1班': '1班']
s.loc['1班': '2班']
# s.loc['李四': '田七']  # 沒有結果
# s.loc[('1班', '李四'): ('2班', '田七')]   # 報錯, 顯式切片只對最外層索引有效# 建議使用隱式切片
s[1: 4]
s.iloc[1: 5]

DataFrame的操作

  • 可以直接使用列名稱來進行列索引
  • 使用行索引需要用iloc(),loc()等函數
  • 無法直接對二級索引進行索引
data = np.random.randint(0, 100, size=(6, 6))index = pd.MultiIndex.from_product( [['1班',  '2班'],['張三', '李四', '王五']]
)
columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['語文', '數學', '英語', '語文', '數學', '英語']
]
df = pd.DataFrame(data=data, index=index, columns=columns)# 獲取元素
df['期中']['數學'][1]df.iloc[1, 3]  # 第1行,第3列(索引)  42
df.loc[('1班', '李四'), ('期末', '語文')]  # 42# 列索引
df['期中']
df['期中']['數學']
df['期中', '數學']
# df[('期中', '數學')]
# df.期中.數學df.iloc[:, 2]
df.iloc[:, [1,2,3]]# 行索引
df.loc['1班']
df.loc['1班'].loc['張三']
df.loc['1班', '張三']
df.loc[('1班', '張三')]df.iloc[1]
df.iloc[[1]]
df.iloc[[1,2,3]]# 切片
# 行切片
df.iloc[1:5]
df.loc['1班' : '2班']
df.loc[('1班', '李四') : ('2班', '李四')]# 列切片
df.iloc[:, 1: 5]
df.loc[:, '期中': '期末']
# df.loc[:, ('期中', '數學'): ('期末', '數學')]  # 報錯

索引的堆疊

使用stack()的時候,level等于哪一個,哪一個就消失,出現在行里。

data = np.random.randint(0, 100, size=(6, 6))
index = pd.MultiIndex.from_product( [['1班',  '2班'],['張三', '李四', '王五']]
)
columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['語文', '數學', '英語', '語文', '數學', '英語']
]
df = pd.DataFrame(data=data, index=index, columns=columns)# stack: 列索引變成行索引
df.stack()  # 默認level=-1 (倒數第一層),將最里層的列索引 變成行索引
df.stack(level=1) df.stack(level=0)  # 將最外層的列索引 變成行索引

使用unstack()的時候,level等于哪一個,哪一個就消失,出現在列里。

# unstack : 將行索引 變成 列索引
df.unstack()
df.unstack(level=1)df.unstack(level=0)

使用fill_value填充

data = np.random.randint(0, 100, size=(6, 6))
index = pd.MultiIndex.from_tuples( (('1班', '張三'), ('1班', '李四'), ('1班', '王五'), ('2班', '趙六'), ('2班', '田七'), ('2班', '孫八'), )
)
columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['語文', '數學', '英語', '語文', '數學', '英語']
]
df2 = pd.DataFrame(data=data, index=index, columns=columns)df2.unstack()
df2.unstack(fill_value=0)

聚合操作

  • 需要指定axis
  • 和unstack()相反,聚合的時候,axis等于哪一個,哪一個就保留。
data = np.random.randint(0, 100, size=(6, 6))
index = pd.MultiIndex.from_tuples( (('1班', '張三'), ('1班', '李四'), ('1班', '王五'), ('2班', '趙六'), ('2班', '田七'), ('2班', '孫八'), )
)
columns = [['期中', '期中', '期中', '期末', '期末', '期末'],['語文', '數學', '英語', '語文', '數學', '英語']
]
df2 = pd.DataFrame(data=data, index=index, columns=columns)# DataFrame聚合操作:求和,平均值,最大值,最小值....
df3 = df.loc['1班', '期中']# axis : 0表式行index, 1表式列columns
df3.sum()
df3.sum(axis=0)  # 對同一列的多行進行求和
df3.sum(axis=1)  # 對同一行的多列進行求和# 多層索引聚合操作
df.sum()  #  默認是對同一列的多行求和
df.sum(axis=1)   # 對同一行的多列求和
df.sum(axis=0, level=0)   # 表式 行 索引中的最外層
df.sum(axis=1, level=0)   # 表式 列 索引中的最外層
df.sum(axis=0, level=1)   # 表式 行 索引中的最里層
df.sum(axis=1, level=1)   # 表式 列 索引中的最里層

Pandas數據合并

  • pd.concat
  • pd.append
  • pd.merge

為了方便,我們首先定義一個生成DataFrame的函數:

def make_df(indexs, columns):    data = [[str(j)+str(i) for j in columns] for i in indexs]df = pd.DataFrame(data=data, index=indexs, columns=columns)return df# 調用
# make_df([1, 2, 3, 4], list('ABCD'))

使用pd.concat()級聯

Pandas使用pd.concat函數,與NumPy中的concatenate函數類似,只是多了一些參數:

簡單級聯

df1 = make_df([1, 2], ['A', 'B'])
df2 = make_df([3, 4], ['A', 'B'])
display(df1, df2)# 上下合并,垂直合并
pd.concat([df1, df2])  # 左右合并,水平合并
pd.concat([df1, df2], axis=1) # 忽略行索引,重置行索引
pd.concat([df1, df2], ignore_index=True)  # 使用多層索引 keys
pd.concat([df1, df2], keys=['x', 'y'])    
# pd.concat([df1, df2], keys=['x', 'y'], axis=1)    

不匹配級聯

不匹配指的是級聯的維度的索引不一致。例如縱向級聯時列索引不一致,橫向級聯時行索引不一致

df3 = make_df([1, 2, 3, 4], ['A', 'B', 'C', 'D'])
df4 = make_df([2, 3, 4, 5], ['B', 'C', 'D', 'E'])
display(df3, df4)# 對應索引沒有值的會自動用NaN填充
pd.concat([df3, df4])# 外連接:補NaN(默認模式), 默認值outer,類似并集, 所有數據都會顯示
pd.concat([df3, df4])
pd.concat([df3, df4], join='outer')# 內連接:只連接匹配的項, 交集, 只顯示共同的列或行
pd.concat([df3, df4], join='inner')

使用append()函數添加

由于在后面級聯的使用非常普遍,因此有一個函數append專門用于在后面添加

df3 = make_df([1, 2, 3, 4], ['A', 'B', 'C', 'D'])
df4 = make_df([2, 3, 4, 5], ['B', 'C', 'D', 'E'])
display(df3, df4)df3.append(df4, sort=True)

使用merge()合并

  • 類似MySQL中表和表之間的合并
  • merge與concat的區別在于,merge需要依據某一共同的行或列來進行合并
  • 使用pd.merge()合并時,會自動根據兩者相同column名稱的那一列,作為key來進行合并。
  • 每一列元素的順序不要求一致

一對一合并

df1 = pd.DataFrame({'name': ['張三', '李四', '王五'],'id' : [1, 2, 3],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 3, 4],'sex': ['男', '女', '女'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)# 合并
# pd.merge(df1, df2)
df1.merge(df2)

多對一合并

df1 = pd.DataFrame({'name': ['張三', '李四', '王五'],'id' : [1, 2, 2],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 3, 4],'sex': ['男', '女', '女'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)# 合并
df1.merge(df2)

多對多合并

df1 = pd.DataFrame({'name': ['張三', '李四', '王五'],'id' : [1, 2, 2],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 2, 4],'sex': ['男', '女', '女'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)# 合并
df1.merge(df2)

key的規范化

  • 使用on=顯式指定哪一列為key,當有多個key相同時使用
df1 = pd.DataFrame({'name': ['張三', '李四', '王五'],'id' : [1, 2, 3],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 3, 4],'name': ['李四', '王五', '趙六'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)# 如果有多列名稱相同, 則需要指定一列作為連接的字段
df1.merge(df2, on='id')
df1.merge(df2, on='name')
  • 使用left_on和right_on指定左右兩邊的列作為key,當左右兩邊的key都不想等時使用
# 如果沒有相同的列名,則需要使用left_on和right_on來分別指定2個表的列作為連接的字段
df1.merge(df2, left_on='id', right_on='id2')
  • 當左邊的列和右邊的index相同的時候,使用right_index=True
df1.merge(df2, left_index=True, right_on='id2')

內合并與外合并

  • 內合并:只保留兩者都有的key(默認模式)
df1 = pd.DataFrame({'name': ['張三', '李四', '王五'],'id' : [1, 2, 3],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 3, 4],'sex': ['男', '女', '女'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)# 內連接: inner join
df1.merge(df2)
df1.merge(df2, how='inner')
  • 外合并 how=‘outer’:補NaN
# 外連接: 
df1.merge(df2, how='outer')
  • 左合并、右合并:how=‘left’,how=‘right’
# 左連接: 
df1.merge(df2, how='left')# 右連接: 
df1.merge(df2, how='right')

添加后綴

  • 當列沖突時,即有多個列名稱相同時,需要使用on=來指定哪一個列作為key,配合suffixes指定沖突列名
  • 可以使用suffixes=自己指定后綴
df1 = pd.DataFrame({'name': ['張三', '李四', '王五'],'id' : [1, 2, 3],'age': [22, 33, 44]
})
df2 = pd.DataFrame({'id' : [2, 3, 4],'name': ['李四', '王五', '趙六'],'job': ['saler', 'CTO', 'Programer']
})
display(df1, df2)df1.merge(df2, on='id', suffixes=['_表1', '_表2'])

merge合并總結

  • 合并有三種現象: 一對一, 多對一, 多對多.
  • 合并默認會找相同的列名進行合并, 如果有多個列名相同,用on來指定.
  • 如果沒有列名相同,但是數據又相同,可以通過left_on, right_on來分別指定要合并的列.
  • 如果想和index合并, 使用left_index, right_index來指定.
  • 如果多個列相同,合并之后可以通過suffixes來區分.
  • 還可以通過how來控制合并的結果, 默認是內合并, 還有外合并outer, 左合并left, 右合并right.

Pandas缺失值處理

None

  • None是Python自帶的,是Python中的空對象。None不能參與到任何計算中。

  • object類型的運算要比int類型的運算慢得多

# 計算不同數據類型求和時間
%timeit np.arange(1e5, dtype=object).sum()
# 6.1 ms ± 122 μs per loop (mean ± std. dev. of 7 runs, 100 loops each)%timeit np.arange(1e5, dtype=np.int32).sum()
# 134 μs ± 7.16 μs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

np.nan(NaN)

  • np.nan是浮點類型,能參與到計算中。但計算的結果總是NaN。
type(np.nan)
# float
  • 但可以使用np.nan*()函數來計算nan,此時會過濾掉nan。
n = np.array([1, 2, 3, np.nan, 5, 6])# np.sum(n)  # nan
np.nansum(n)np.nan + 10

pandas中的None與NaN

pandas中None與np.nan都視作np.nan

  • 創建DataFrame
data = np.random.randint(0 ,100, size=(5, 5))
df = pd.DataFrame(data=data, columns=list('ABCDE'))# 修改數據,增加2種nan
df.loc[2, 'B'] = np.nan
df.loc[3, 'C'] = None
display(df)# 查看結果
df.loc[2, 'B']  # nan
df.loc[3, 'C']  # nan

pandas中None與np.nan的操作

  • isnull()
  • notnull()
  • all()
  • any()
  • dropna(): 過濾丟失數據
  • fillna(): 填充丟失數據

(1)判斷函數

  • isnull()
  • notnull()
# isnull
df.isnull()# notnull
df.notnull()# all(): 必須全部為True才為True, 類似and
# any(): 只要有一個為True即為True,  類似ordf.isnull().any()  # 常用, 盡可能找到所有的空值
# df.isnull().all()df.notnull().all()  # 常用,盡可能找到所有的空值
# df.notnull().any()df.isnull().any(axis=1)  # axis=1 表式列,判斷一行中的每一列數據進行判斷
df.notnull().all(axis=1)
  • 使用bool值索引過濾數據
# 行過濾
# 將df中有空的列過濾掉
cond = df.isnull().any(axis=1)
# display(cond, ~cond)
# ~ 取反
df[~cond]cond = df.notnull().all(axis=1)
# cond
df[cond]# 列過濾
cond = df.notnull().all()
# cond
df.loc[:, cond]cond = df.isnull().any()
# cond
df.loc[:, ~cond]

(2) 過濾函數

  • dropna()

可以選擇過濾的是行還是列(默認為行)

df.dropna()  # 默認是刪除有空的行
df.dropna(axis=1)  # 刪除有空的列

也可以選擇過濾的方式 how = ‘all’

df.dropna(how='any')  # 默認值,默認有空就會刪除
df.dropna(how='all', axis=1)  # 所有的值都為空(整行或整列為空),才刪除

inplace=True 修改原數據

df2 = df.copy()# inplace=True: 表式修改原數據
df2.dropna(inplace=True)
df2

(3) 填充函數 Series/DataFrame

  • fillna()
# 填充
df.fillna(value=100)df2 = df.copy()
df2.loc[1, 'B'] = np.nan
df2.loc[4, 'C'] = None
display(df2)# limit: 限制對應維度上填充的次數
df2.fillna(value=100, limit=1, inplace=True)# 可以選擇前向填充還是后向填充
# method : {'backfill', 'bfill', 'pad', 'ffill', None}, default None
#     Method to use for filling holes in reindexed Series
#     pad/ffill: propagate last valid observation forward to next valid
#     backfill/bfill: use next valid observation to fill gap.df.fillna(method='ffill')  # 用上面數據來填充自己
# df.fillna(method='pad')df.fillna(method='bfill')  # 用下面數據來填充自己
# df.fillna(method='backfill')df.fillna(method='ffill', axis=1)  # 用左邊數據來填充自己df.fillna(method='bfill', axis=1)  # 用右邊數據來填充自己

Pandas處理重復值和異常值

刪除重復行

  • 使用duplicated()函數檢測重復的行,返回元素為布爾類型的Series對象
  • 每個元素對應一行,如果該行不是第一次出現,則元素為True
# 讓第一行和第二行重復
df.loc[1] = df.loc[2]# 判斷是否和前面的行重復了
df.duplicated()# df.duplicated(keep='first')  # 保留第一行
# df.duplicated(keep='last')  # 保留最后一行
# df.duplicated(keep=False)  # 標記所有重復行df.loc[1, 'D'] = 'DDD'
# subset: 子集, 只需要子集相同就可以判斷重復
df.duplicated(subset=['A', 'B', 'C'])

使用drop_duplicates()函數刪除重復的行

df.drop_duplicates(subset=['A', 'B', 'C'])
df.drop_duplicates(subset=['A', 'B', 'C'], keep='last')

映射

映射的含義:創建一個映射關系列表,把values元素和一個特定的標簽或者字符串綁定

包含三種操作:

  • replace()函數:替換元素
  • map()函數:處理某一單獨的列, 最重要
  • rename()函數:替換索引

replace()函數:替換元素

使用replace()函數,對values進行替換操作

index = ['魯班', '張三豐', '張無忌', '杜甫', '李白']
columns = ['Python', 'Java', 'H5', 'Pandas']
data = np.random.randint(0, 100, size=(5, 4))df = pd.DataFrame(data=data, index=index, columns=columns)# replace還經常用來替換NaN元素
df.replace({1: 100})

map()函數:

適合處理某一單獨的列

df2 = df.copy()
df2# map是Series調用,不能使用DataFrame調用
df2['Python'].map({12: 100, 11: 90})# map()函數中可以使用lambda函數
# 新建一列
df2['NumPy'] = df2['Python'].map(lambda x: x+100)
df2# 新增一列:判斷java成績是否及格
df2['是否及格'] = df2['Java'].map(lambda n:  "及格" if n>=60 else "不及格")
df2# 新增一列:判斷Java成績的等級(>=80優秀,>=60及格,<60不及格)
def fn(n):if n >= 80:return '優秀'elif n >= 60:return '及格'return '不及格'df2['等級'] = df2['Java'].map(fn)
df2

rename()函數:替換索引

df3 = df.copy()
df3# 更改索引名稱
df3.rename({'魯班': "Mr Lu"})  # 默認更改行索引
df3.rename({'Python': 'PYTHON'}, axis=1)  # 更改列索引df3.rename(index={'魯班': "Mr Lu"})  # 更改行索引
df3.rename(columns={'Python': 'PYTHON'})  # 更改列索引

apply()函數:

既支持 Series,也支持 DataFrame

df = pd.DataFrame(data=np.random.randint(0, 10, size=(5,3)),index=list('ABCDE'),columns=['Python', 'NumPy', 'Pandas'])# 用于Series,其中x是Series中元素
df['Python'].apply(lambda x:True if x >5 else False) # 用于DataFrame,其中的x是DataFrame中列或者行,是Series
df.apply(lambda x : x.median(), axis=0)  # 列的中位數
df.apply(lambda x : x.median(), axis=1)  # 行的中位數# 自定義方法
def convert(x): return (np.round(x.mean(), 1), x.count())
df.apply(convert, axis=1)  # 行平均值,計數# applymap: DataFrame專有, 其中的x是DataFrame中每個元素
df.applymap(lambda x : x + 100) # 計算DataFrame中每個元素

transform()函數

df = pd.DataFrame(data=np.random.randint(0, 10, size=(10,3)),index=list('ABCDEFHIJK'),columns=['Python', 'NumPy', 'Pandas'])# 1、一列執行多項計算
df['Python'].transform([np.sqrt, np.exp]) # Series處理# 2、多列執行不同計算
def convert(x):if x.mean() > 5:x *= 10else:x *= -10return xdf.transform({'Python':convert,'NumPy':np.max,'Pandas':np.min}) 

異常值檢測和過濾

  • describe(): 查看每一列的描述性統計量
# 查看每一列的描述性統計
df.describe()
df.describe([0.3, 0.4, 0.5, 0.9, 0.99])  # 指定百分位數
df.describe([0.3, 0.4, 0.5, 0.9, 0.99]).T  # 轉置,行和列轉換,在列比較多的情況下使用
  • df.std() : 可以求得DataFrame對象每一列的標準差
df.std()
  • df.drop(): 刪除特定索引
df4 = df.copy()
df4df4.drop('魯班')  # 默認刪除行
df4.drop('Java', axis=1)  # 刪除列df4.drop(index='魯班')  # 刪除行
df4.drop(columns='H5')  # 刪除列df4.drop(columns=['Java', 'Pandas'])  # 同時刪除多列
  • unique() : 唯一,去重
index = ['魯班', '張三豐', '張無忌', '杜甫', '李白']
columns = ['Python', 'Java', 'H5', 'Pandas']
data = np.random.randint(0, 10, size=(5, 4))df = pd.DataFrame(data=data, index=index, columns=columns)
df# unique() : 要用于Series, 不能用于DataFrame
df['Python'].unique()
  • query() : 按條件查詢
# ==, >, <, 
# in
# and &
# or  |df.query('Python == 5')
df.query('Python > 5')df.query('Python==5 and Java==5')
df.query('Python==5 & Java==5')
df.query('Python==5 or Java==6')
df.query('Python==5 | Java==6')# 使用變量
n = 5
df.query('Python > @n')  # @n 使用變量
df.query('Python in [3, 4, 5, 6]')
m = [3, 4, 5, 6]
df.query('Python in @m')
  • df.sort_values(): 根據值排序

  • df.sort_index(): 根據索引排序

index = ['魯班', '張三豐', '張無忌', '杜甫', '李白']
columns = ['Python', 'Java', 'H5', 'Pandas']
data = np.random.randint(0, 100, size=(5, 4))df = pd.DataFrame(data=data, index=index, columns=columns)
dfdf.sort_values('Python')  # 默認按照列名排序,默認升序
df.sort_values('Python', ascending=False)    # 降序
df.sort_values('魯班', axis=1)  # 按照行索引或列索引排序
df.sort_index(ascending=True, axis=1)
  • df.info(): 查看數據信息
df.info()

抽樣

  • 使用.take()函數排序

  • 可以借助np.random.permutation()函數隨機排序

# 使用前面的df2
df2.take([4, 1, 2, 3, 0])   # 行排列
df2.take([1, 0, 2, 3, 4, 5, 6], axis=1)  # 列排列# 隨機排序
np.random.permutation([0, 1, 2, 3, 4, 5])# 無放回抽樣:依次拿取,沒有重復值
df2.take(np.random.permutation([0, 1, 2, 3, 4]))# 有放回抽樣: 可能出現重復值
# 當DataFrame規模足夠大時,直接使用np.random.randint()函數,就配合take()函數實現隨機抽樣
np.random.randint(0, 10, size=10)
df2.take(np.random.randint(0, 5, size=5))

Pandas數學函數

  • 聚合函數
df = pd.DataFrame(data=np.random.randint(0,100,size = (20,3)))df.count() # 非空值的數量
df.max() # 最大值,axis=0/1
df.min() # 最小值, axis=0/1
df.median() # 中位數
df.sum() # 求和
df.mean(axis=1) # 每一行的平均值df[0].value_counts() # 統計元素出現次數
df.cumsum() # 累加
df.cumprod() # 累乘# 方差: 當數據分布比較分散(即數據在平均數附近波動較大)時,各個數據與平均數的差的平方和較大,方差就較大;當數據分布比較集中時,各個數據與平均數的差的平方和較小。因此方差越大,數據的波動越大;方差越小,數據的波動就越小
df.var() # 方差# 標準差 = 方差的算術平方根
df.std() # 標準差

其他數學函數

協方差
- 兩組數值中每對變量的偏差乘積的平均值
- 協方差>0 : 表式兩組變量正相關
- 如果兩個變量的變化趨勢一致,也就是說如果其中一個大于自身的期望值時另外一個也大于自身的期望值,那么兩個變量之間的協方差就是正值;
- 協方差<0 : 表式兩組變量負相關
- 如果兩個變量的變化趨勢相反,即其中一個變量大于自身的期望值時另外一個卻小于自身的期望值,那么兩個變量之間的協方差就是負值。
- 協方差=0 : 表式兩組變量不相關

相關系數

  • 相關系數r = X與Y的協方差 / (X的標準差 * Y的標準差)
  • 相關系數值的范圍在-1和+1之間
  • r>0為正相關,r<0為負相關。r=0表示不相關
  • r 的絕對值越大,相關程度越高
  • 兩個變量之間的相關程度,一般劃分為四級:
    • 如兩者呈正相關,r呈正值,r=1時為完全正相關;
    • 如兩者呈負相關則r呈負值,而r=-1時為完全負相關,完全正相關或負相關時,所有圖點都在直線回歸線上;點分布在直線回歸線上下越離散,r的絕對值越小。
    • 相關系數的絕對值越接近1,相關越密切;越接近于0,相關越不密切。
    • 當r=0時,說明X和Y兩個變量之間無直線關系。
    • 通常|r|大于0.8時,認為兩個變量有很強的線性相關性。
# 協方差
#   兩組數值中每對變量的偏差乘積的平均值df.cov() 
df[0].cov(df[1])  # 第0列 和 第1列的協方差# 相關系數 = X與Y的協方差 / (X的標準差 * Y的標準差)
df.corr() # 所有屬性相關性系數
df.corrwith(df[2]) # 單一屬性相關性系數

協方差: C o v ( X , Y ) = ∑ 1 n ( X i ? X  ̄ ) ( Y i ? Y  ̄ ) n ? 1 Cov(X,Y) = \frac{\sum\limits_1^n(X_i - \overline{X})(Y_i - \overline{Y})}{n-1} Cov(X,Y)=n?11n?(Xi??X)(Yi??Y)?

相關性系數: r ( X , Y ) = C o v ( X , Y ) V a r [ X ] ? V a r [ Y ] r(X,Y) = \frac{Cov(X,Y)}{\sqrt{Var[X]*Var[Y]}} r(X,Y)=Var[X]?Var[Y] ?Cov(X,Y)?

數據分組聚合

數據聚合是數據處理的最后一步,通常是要使每一個數組生成一個單一的數值。

分組

數據聚合處理:

  • 分組:先把數據分為幾組
  • 用函數處理:為不同組的數據應用不同的函數以轉換數據
  • 合并:把不同組得到的結果合并起來

數據分類處理的核心: groupby()函數

# 創建DataFrame
df = pd.DataFrame({'color': ['green', 'green', 'yellow', 'blue', 'blue', 'yellow', 'yellow'],'price': [4, 5, 3, 2, 7, 8, 9]}
)
df# 使用.groups屬性查看各行的分組情況:
# 根據color進行分組
df.groupby(by='color')
df.groupby(by='color').groups# 分組 + 聚合
df.groupby(by='color').sum()
分組聚合練習:

假設菜市場張大媽在賣菜,有以下屬性:

  • 菜品(item):蘿卜,白菜,辣椒,冬瓜

  • 顏色(color):白,青,紅

  • 重量(weight)

  • 價格(price)

  1. 要求以屬性作為列索引,新建一個ddd
  2. 對ddd進行聚合操作,求出顏色為白色的價格總和
  3. 對ddd進行聚合操作,求出蘿卜的所有重量以及平均價格
  4. 使用merge合并總重量及平均價格
ddd = pd.DataFrame(data={"item": ["蘿卜","白菜","辣椒","冬瓜","蘿卜","白菜","辣椒","冬瓜"],'color':["白","青","紅","白","青","紅","白","青"],'weight': [10,20,10,10,30,40,50,60],'price': [0.99, 1.99, 2.99, 3.99, 4, 5, 6,7]}
)
ddd# 2. 對ddd進行聚合操作,求出顏色為白色的價格總和
ddd.groupby('color')['price'].sum()  # Series
ddd.groupby('color')[['price']].sum()  # DataFrame
ddd.groupby('color')[['price']].sum() .loc[['白']]# 3. 對ddd進行聚合操作,求出蘿卜的所有重量以及平均價格
df1 = ddd.groupby('item')[['weight']].sum()
df2= ddd.groupby('item')[['price']].mean()# 4.使用merge合并總重量及平均價格
# display(df1, df2)
df1.merge(df2, left_index=True, right_index=True)

Pandas加載數據

csv數據

data = np.random.randint(0,50,size=(10,5))
df = pd.DataFrame(data=data, columns=['Python','Java','Go','C','JS'])# 保存到csv
df.to_csv('data.csv',sep=',',  # 文本分隔符,默認是逗號header=True, # 是否保存列索引# 是否保存行索引,保存行索引,文件被加載時,默認行索引會作為一列index=True)  # 加載csv數據
pd.read_csv('data.csv',sep=',', # 默認是逗號header=[0], # 指定列索引index_col=0)  # 指定行索引pd.read_table('data.csv', # 和read_csv類似,讀取限定分隔符的文本文件sep=',',header=[0], # 指定列索引index_col=0  # 指定行索引) 

excel數據

data = np.random.randint(0, 50, size=(10,5))
df = pd.pDataFrame(data=data, columns=['Python','Java','Go','C','JS'])# 保存到excel文件
df.to_excel('data.xls',sheet_name='sheet1',# Excel中工作表的名字header=True, # 是否保存列索引index=False) # 是否保存行索引# 讀取excel
pd.read_excel('data.xls',sheet_name=0, # 讀取哪一個Excel中工作表,默認第一個, 也可以寫工作表名稱header=0, # 使用第一行數據作為列索引names=list('ABCDE'), # 替換行索引index_col=1) # 指定行索引,B作為行索引

MySQL數據

  • 需要安裝pymysql
    • pip install pymysql -i https://pypi.tuna.tsinghua.edu.cn/simple
  • 需要安裝sqlalchemy:
    • pip install sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple
    • sqlalchemy是Python語言下的數據庫引擎庫, 在Django/Flask中常用ORM庫
from sqlalchemy import create_enginedata = np.random.randint(0,150,size=(150,3))
df = pd.DataFrame(data=data, columns=['Python','Pandas','PyTorch'])# 數據庫連接
# root: MySQL用戶名
# 123456: MySQL密碼
# localhost: 本機
# db: 數據庫名(提前創建)
conn = create_engine('mysql+pymysql://root:123456@localhost/db')# 保存到MySQL
df.to_sql('score', # 表名(會自動創建表)conn, # 數據庫連接index=False,  # 是否保存行索引if_exists='append') # 如果表名存在,追加數據# 從MySQL中加載數據
pd.read_sql('select * from score', # sql查詢語句conn, # 數據庫連接index_col='Python') # 指定行索引名

Pandas分箱操作

  • 分箱操作就是將連續型數據離散化。
  • 分箱操作分為等距分箱和等頻分箱。
data = np.random.randint(0,150,size=(150,3))
df = pd.DataFrame(data=data, columns=['Python','Pandas','PyTorch'])# 對Python列進行分箱
df.Python.values# 1、等寬分箱
pd.cut(df.Python, bins=4)# 指定寬度分箱
pd.cut(df.Python, # 分箱數據bins=[0, 30, 60, 80, 100], # 分箱斷點right=False, # 左閉右開labels=['D','C','B','A']) # 分箱后分類標簽# 2、等頻分箱
pd.qcut(df.Python, # 分箱數據q=4, # 4等份labels=['差', '中', '良', '優']) # 分箱后分類標簽

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/38420.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/38420.shtml
英文地址,請注明出處:http://en.pswp.cn/web/38420.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

光照老化試驗箱:材料耐久性的“時間加速器”

光照老化試驗箱&#xff1a;材料耐久性的“時間加速器”概述 光照老化試驗箱是一種模擬自然光照條件下材料老化過程的設備&#xff0c;廣泛應用于材料科學領域的耐久性能評估。通過模擬日光中的紫外線、熱輻射等環境因素&#xff0c;加速材料老化過程&#xff0c;以此來驗證材…

redhawk:tech file與lefdef layer name不匹配問題

我正在「拾陸樓」和朋友們討論有趣的話題&#xff0c;你?起來吧&#xff1f; 拾陸樓知識星球入口 一些工藝廠商給的redhawk tech file是加密的&#xff0c;讀完tech file再讀lef/def會報錯&#xff0c;根本不知道問題在哪&#xff0c;他們一般會搭配給一個layer map&#xff…

分解+降維+預測!多重創新!直接寫核心!EMD-KPCA-Transformer多變量時間序列光伏功率預測

分解降維預測&#xff01;多重創新&#xff01;直接寫核心&#xff01;EMD-KPCA-Transformer多變量時間序列光伏功率預測 目錄 分解降維預測&#xff01;多重創新&#xff01;直接寫核心&#xff01;EMD-KPCA-Transformer多變量時間序列光伏功率預測效果一覽基本介紹程序設計參…

【簡單講解神經網絡訓練中batch的作用】

&#x1f3a5;博主&#xff1a;程序員不想YY啊 &#x1f4ab;CSDN優質創作者&#xff0c;CSDN實力新星&#xff0c;CSDN博客專家 &#x1f917;點贊&#x1f388;收藏?再看&#x1f4ab;養成習慣 ?希望本文對您有所裨益&#xff0c;如有不足之處&#xff0c;歡迎在評論區提出…

Maven依賴解析過程詳細講解

Maven依賴解析是一個遞歸的過程&#xff0c;涉及從項目的POM文件開始&#xff0c;逐步解析直接依賴和傳遞依賴。以下是詳細的解析過程&#xff1a; 讀取項目的POM文件&#xff1a; Maven首先讀取項目的POM文件 (pom.xml)&#xff0c;該文件定義了項目的直接依賴。 解析直接依賴…

STM32第十五課:LCD屏幕及應用

文章目錄 需求一、LCD顯示屏二、全屏圖片三、數據顯示1.顯示歡迎詞2.顯示溫濕度3.顯示當前時間 四、需求實現代碼 需求 1.在LCD屏上顯示一張全屏圖片。 2.在LCD屏上顯示當前時間&#xff0c;溫度&#xff0c;濕度。 一、LCD顯示屏 液晶顯示器&#xff0c;簡稱 LCD(Liquid Cry…

node_sqlite3.node is not a valid win32 application

electron打包報錯 使用electron在linux平臺打包含有sqlite3的項目為win32應用時在運行階段&#xff0c;有時會遇到下面的錯誤 node_sqlite3.node is not a valid win32 application出現該錯誤的原因主要是在64bit的linux環境中&#xff0c;sqlite3默認build出來的二進制文件不…

【Windows】Visual Studio Installer下載緩慢解決辦法

【Windows】Visual Studio Installer下載緩慢解決辦法 1.背景2.分析3.結果 1.背景 使用visual studio在線安裝包進行IDE安裝&#xff0c;發現下載幾乎停滯&#xff0c;網速幾乎為零。 經過排查并不是因為實際網絡帶寬導致。 這里涉及DNS知識&#xff1b; DNS&#xff08;Dom…

消防認證-防火卷簾

一、消防認證 消防認證是指消防產品符合國家相關技術要求和標準&#xff0c;且通過了國家認證認可監督管理委員會審批&#xff0c;獲得消防認證資質的認證機構頒發的證書&#xff0c;消防產品具有完好的防火功能&#xff0c;是住房和城鄉建設領域驗收的重要指標。 二、認證依據…

TP8 JS(html2canvas) 把DIV內容生成二維碼并與背景圖、文字組合生成分享海報

方法一&#xff1a;前端JS生成(推薦) 注意&#xff1a; 1.這個網頁只能截圖圖片效果代碼&#xff0c;其它任何html效果都不能有&#xff0c;不然截圖就不準確 2.如果要生成的圖片DIV內容中引用了第三個方的圖片&#xff0c;就是不使用同一個域名下的圖片&#xff0c;需要把后…

Python爬取淘寶商品評價信息實戰:從零到一的高效教程

引言&#xff1a;揭秘淘寶數據金礦 在電商領域&#xff0c;用戶評價是衡量產品優劣的金標準。作為Python爬蟲工程師&#xff0c;掌握從淘寶這座數據金礦中挖掘寶貴評價信息的技能至關重要。本文將帶你手把手實操&#xff0c;用Python爬蟲技術獲取淘寶商品的評價信息&#xff0…

Docker多階段構建Node.js應用程序

Node.js 應用程序 創建一個目錄來存放你的項目文件&#xff0c;然后在該目錄下創建以下文件。 package.json {"name": "docker-node-test","version": "1.0.0","description": "A simple Node.js app for Docker mu…

【折騰筆記】使用 PicList + Lsky Pro 對圖片進行雙重壓縮

前言 因為服務器的帶寬比較小,為了提高網站的訪問速度,網站內的圖片進行壓縮是必不可少的。另外將圖片轉換成WebP的格式可以減小文件大小、加快加載速度、支持高級特性(如透明度和動畫),以及減少存儲需求,為網站提供了顯著的性能。需要提前安裝好PicList客戶端和Lsky Pr…

最快33天錄用!一投就中的醫學4區SCI,幾乎不退稿~

【SciencePub學術】今天小編給大家推薦2本生物醫學領域的SCI&#xff0c;此期刊為我處目前合作的重點期刊&#xff01;影響因子0-3.0之間&#xff0c;最重要的是審稿周期較短&#xff0c;對急投的學者較為友好&#xff01; 醫學醫藥類SCI 01 / 期刊概況 【期刊簡介】IF&…

那些好用的 Vue3 的工具搭子!!【送源碼】

2020 年 9 月 18 日 Vue3 的正式發布已經過去了大約 3 年 9 個月左右&#xff01;&#xff01;&#xff01; 隨著 Vue3 版本的逐漸成熟&#xff0c;我們的前端世界也迎來了一系列令人振奮的更新和工具。Vue 生態圈的持續擴大&#xff0c;無疑為前端開發人員帶來了前所未有的便…

通過pycharm使用git和github的步驟

一、在Pycharm工具中配置集成Git和GitHub。 1.集成Git。 打開Pycharm, 點擊File-->Settins-->Version Control-->Git 然后在 Path to Git executable中選擇本地的git.exe路徑。如下圖&#xff1a; 2.集成GitHub 打開Pycharm, 點擊File-->Settins-->Version…

探索未來遠程調試新紀元——《串口網口遠程調試軟件》:無縫連接,高效調試

文章目錄 前言一、無縫連接&#xff0c;突破距離限制二、高效調試&#xff0c;提升工作效率三、安全可靠&#xff0c;保護數據安全四、用戶友好&#xff0c;簡化操作流程五、軟件地址六、遠程調試軟件 七、基本操作1、訂閱主題2、連接3、串口調試4、網口調試 八、軟件地址結束語…

PO模式登錄測試

項目實踐 登陸項目測試 get_driver import page from selenium import webdriverclass GetDriver:driver Noneclassmethoddef get_driver(cls):if cls.driver is None:cls.driver webdriver.Edge()cls.driver.maximize_window()cls.driver.get(page.url)return cls.drivercl…

Java高風險漏洞與修復之——LDAP injection(LDAP注入)

LDAP注入介紹 LDAP注入是一種攻擊技術,它可以利用應用程序中的安全漏洞對LDAP(輕量級目錄訪問協議)服務進行惡意查詢或修改操作。當應用程序未能適當地清理用戶的輸入內容,將其嵌入到LDAP查詢中時,就可能發生LDAP注入。攻擊者通過注入未經授權的指令或條件來操縱查詢結果…

【代碼隨想錄訓練營】【Day 66】【圖論-3】| 卡碼 101-104

【代碼隨想錄訓練營】【Day 66】【圖論-3】| 卡碼 101-104 需強化知識點 103&#xff0c;104 優化思路 題目 101. 孤島的總面積 此處 area 多余 def dfs(grid, x, y, area):dirs [[0, 1], [0, -1], [1, 0], [-1, 0]]m, n len(grid), len(grid[0])area[0] 1grid[x][y] …