Python數據處理基礎(學習筆記分享)

Python數據處理入門

常用庫學習

numpy

NumPy(Numerical Python) 是 Python 中用于高效數值計算的庫,核心是提供一個強大的 ndarray?(多維數組)對象,類似于 C/C++ 中的數組,但支持更豐富的操作,比如切片、廣播、線性代數等。

基本用法:

import numpy as np
創建數組
a = np.array([1, 2, 3])            # 一維數組
b = np.array([[1, 2], [3, 4]])     # 二維數組print(a)  # [1 2 3]
print(b)  # [[1 2]#  [3 4]]

說明:使用 np.array()? 可以把列表或嵌套列表轉換為 NumPy 數組。


查看數組形狀和屬性
print(a.shape)   # (3,)   → 一維數組,3個元素
print(b.shape)   # (2, 2) → 2行2列print(b.ndim)    # 2      → 二維數組
print(b.dtype)   # int64  → 元素類型

常用數組創建方法
print(np.zeros((2, 3)))   # 全0數組
# [[0. 0. 0.]
#  [0. 0. 0.]]print(np.ones((2, 2)))    # 全1數組
# [[1. 1.]
#  [1. 1.]]print(np.eye(3))          # 單位矩陣
# [[1. 0. 0.]
#  [0. 1. 0.]
#  [0. 0. 1.]]print(np.arange(0, 5, 1)) # 等差數組:[0 1 2 3 4]
print(np.linspace(0, 1, 5)) # 等間距:[0. 0.25 0.5 0.75 1.]

數組運算
a = np.array([1, 2, 3])
b = np.array([4, 5, 6])print(a + b)    # [5 7 9]
print(a - b)    # [-3 -3 -3]
print(a * 2)    # [2 4 6]
print(a ** 2)   # [1 4 9]

說明:NumPy 支持逐元素運算,不需要寫循環。


數組統計函數
a = np.array([1, 2, 3, 4])print(np.sum(a))     # 總和:10
print(np.mean(a))    # 平均數:2.5
print(np.max(a))     # 最大值:4
print(np.min(a))     # 最小值:1
print(np.std(a))     # 標準差

數組索引和切片
a = np.array([[10, 20, 30],[40, 50, 60]])print(a[0, 1])    # 第1行第2列 → 20
print(a[1])       # 第2行 → [40 50 60]
print(a[:, 0])    # 第1列 → [10 40]

說明:二維數組使用 a[行, 列]? 方式訪問。


形狀變換
a = np.arange(6)           # [0 1 2 3 4 5]
b = a.reshape((2, 3))      # 改成2行3列print(b)
# [[0 1 2]
#  [3 4 5]]

廣播機制(自動對齊維度)
a = np.array([[1, 2], [3, 4]])
b = np.array([10, 20])print(a + b)
# [[11 22]
#  [13 24]]

說明:b? 自動擴展為二維數組 [10, 20]?,重復到每一行。


矩陣乘法 vs 元素乘法
a = np.array([[1, 2],[3, 4]])
b = np.array([[5, 6],[7, 8]])print(a * b)        # 元素乘法
# [[ 5 12]
#  [21 32]]print(np.dot(a, b)) # 矩陣乘法
# [[19 22]
#  [43 50]]

數組條件篩選
a = np.array([1, 2, 3, 4, 5])
print(a[a > 3])     # [4 5]

復制與原地修改
a = np.array([1, 2, 3])
b = a.copy()       # 深拷貝,不影響原數組
b[0] = 99print(a)           # [1 2 3]
print(b)           # [99 2 3]

?


pandas

Pandas(Python Data Analysis Library) 是 Python 中用于 數據分析與處理 的核心庫,提供了強大的 DataFrame? 和 Series? 兩種數據結構,適用于結構化數據(表格、Excel、數據庫)的讀取、清洗、分析、可視化等。

基本用法:

import pandas as pd
創建 Series(一維數據)
s = pd.Series([10, 20, 30, 40])
print(s)
# 0    10
# 1    20
# 2    30
# 3    40
# dtype: int64

說明:Series? 是帶標簽的一維數組,默認索引為 0 開始的整數。


創建 DataFrame(二維表格)
data = {'name': ['Alice', 'Bob', 'Charlie'],'age': [25, 30, 35],'city': ['NY', 'LA', 'Chicago']}df = pd.DataFrame(data)
print(df)
#      name  age     city
# 0   Alice   25       NY
# 1     Bob   30       LA
# 2  Charlie   35  Chicago

說明:DataFrame? 是 Pandas 的核心表格型結構,類似于 Excel 表。


查看數據基本信息
print(df.shape)      # (3, 3) → 3行3列
print(df.columns)    # 列名:Index(['name', 'age', 'city'], dtype='object')
print(df.index)      # 行索引:RangeIndex(start=0, stop=3, step=1)
print(df.dtypes)     # 每列的數據類型

讀取常見文件
# 讀取 CSV 文件
df = pd.read_csv('data.csv')# 讀取 Excel 文件
df = pd.read_excel('data.xlsx')# 保存為 CSV 文件
df.to_csv('output.csv', index=False)

訪問列與行
print(df['name'])       # 訪問單列(Series)
print(df[['name', 'age']])  # 多列(DataFrame)print(df.loc[0])        # 按標簽訪問第1行
print(df.iloc[1])       # 按位置訪問第2行

說明:loc? 用標簽,iloc? 用索引位置。


條件篩選
print(df[df['age'] > 28])
# 篩選出 age > 28 的行

添加、修改與刪除列
df['salary'] = [5000, 6000, 7000]  # 添加新列print(df['age'] * 2)               # 修改方式:表達式df.drop('city', axis=1, inplace=True)  # 刪除列

缺失值處理
df = pd.DataFrame({'name': ['Alice', 'Bob', None],'age': [25, None, 35]
})print(df.isnull())          # 判斷是否為空
print(df.dropna())          # 刪除含缺失值的行
print(df.fillna(0))         # 填充缺失值

分組與聚合
df = pd.DataFrame({'dept': ['IT', 'HR', 'IT', 'HR'],'salary': [6000, 5000, 7000, 5500]
})print(df.groupby('dept').mean())
# 按部門求平均工資

排序與唯一值
print(df.sort_values('salary', ascending=False))  # 按工資降序
print(df['dept'].unique())    # 唯一值

合并與拼接
df1 = pd.DataFrame({'id': [1, 2], 'name': ['Alice', 'Bob']})
df2 = pd.DataFrame({'id': [1, 2], 'score': [90, 85]})print(pd.merge(df1, df2, on='id'))  # 按 id 合并

應用函數與映射
df['age_group'] = df['age'].apply(lambda x: 'adult' if x >= 30 else 'young')
print(df)

說明:使用 apply()? 可以對每個元素應用函數。


導出結果
df.to_csv('result.csv', index=False)
df.to_excel('result.xlsx', index=False)

json

json(JavaScript Object Notation) 是一種輕量級的數據交換格式,Python 內置了 json? 模塊來方便地進行 JSON 數據的解析和生成,常用于數據持久化前后端通信等場景。

基本用法:

import json
Python 與 JSON 的對應關系:
Python 類型JSON 類型
?dict?object
?list?、tuple?array
?str?string
?int?/float?number
?True?/False?true / false
?None?null

Python 轉 JSON 字符串(序列化)
data = {"name": "Alice", "age": 25, "is_student": False}
json_str = json.dumps(data)print(json_str)
# {"name": "Alice", "age": 25, "is_student": false}

說明:json.dumps()? 可以把 Python 對象轉換為 JSON 字符串。


JSON 字符串轉 Python 對象(反序列化)
json_str = '{"name": "Alice", "age": 25, "is_student": false}'
data = json.loads(json_str)print(data)
# {'name': 'Alice', 'age': 25, 'is_student': False}

說明:json.loads()? 可以把 JSON 字符串解析為 Python 對象。


序列化時格式化輸出
data = {"name": "Bob", "scores": [90, 85, 88]}
print(json.dumps(data, indent=2))
# {
#   "name": "Bob",
#   "scores": [
#     90,
#     85,
#     88
#   ]
# }

說明:通過 indent? 參數可控制縮進,增加可讀性。


中文處理
data = {"name": "小明", "age": 18}
print(json.dumps(data, ensure_ascii=False))
# {"name": "小明", "age": 18}

說明:默認中文會轉成 Unicode,用 ensure_ascii=False? 可以保留中文。


寫入 JSON 文件
data = {"title": "Python", "level": "beginner"}with open("data.json", "w", encoding="utf-8") as f:json.dump(data, f, ensure_ascii=False, indent=2)使用 with open(...) 打開一個文件:"data.json":要寫入的文件名(如果沒有會自動創建)"w":寫入模式(write),會覆蓋原有內容encoding="utf-8":指定編碼為 UTF-8,確保中文不會亂碼f 是文件對象,代表這個打開的文件

說明:json.dump()? 將 Python 對象寫入文件,支持格式化輸出。


從 JSON 文件讀取
with open("data.json", "r", encoding="utf-8") as f:data = json.load(f)print(data)

說明:json.load()? 用于從文件中讀取并解析 JSON 數據。


復雜嵌套結構解析
json_str = '''
{"user": {"name": "Tom","skills": ["Python", "C++"]}
}
'''data = json.loads(json_str)
print(data["user"]["skills"][0])  # Python

說明:嵌套結構可通過多級鍵訪問。


轉換時處理非默認類型
import datetimedef custom(obj):if isinstance(obj, datetime.datetime):return obj.isoformat()now = datetime.datetime.now()
print(json.dumps({"time": now}, default=custom))
# {"time": "2025-07-28T11:30:00.123456"}

說明:使用 default? 參數可以處理自定義類型。


字符串與字典互轉小技巧
s = '{"x": 1, "y": 2}'
d = json.loads(s)
s2 = json.dumps(d)print(type(d))   # <class 'dict'>
print(type(s2))  # <class 'str'>

防止類型錯誤
# 錯誤示例:集合不是 JSON 可序列化類型
data = {"nums": {1, 2, 3}}
# json.dumps(data) 會報錯# 解決方式:轉換為 list
data["nums"] = list(data["nums"])
print(json.dumps(data))

說明:json? 只支持部分 Python 類型,需提前轉換。


與字典深拷貝的配合
import copy
original = {"a": 1, "b": [1, 2]}# 用 json 序列化方式做深拷貝
clone = json.loads(json.dumps(original))clone["b"][0] = 999
print(original)  # {'a': 1, 'b': [1, 2]}
print(clone)     # {'a': 1, 'b': [999, 2]}

說明:json? 也可以作為一種簡易深拷貝手段(前提是可序列化)。


PIL / Pillow

Pillow(PIL 的分支) 是 Python 中用于圖像處理的強大庫,支持打開、編輯、保存多種格式的圖片。Pillow 是原始 PIL 庫的增強版,常用于圖像縮放、裁剪、轉換、繪圖等操作。

基本用法:

from PIL import Image

打開和顯示圖片
img = Image.open("example.jpg")  # 打開圖片
img.show()                       # 使用默認圖片查看器顯示

說明:使用 Image.open()? 加載本地圖片,show()? 會調用系統圖片查看器。


查看圖片屬性
print(img.format)    # 圖片格式,如 JPEG
print(img.size)      # 尺寸:如 (寬, 高)
print(img.mode)      # 模式:如 RGB、L、RGBA

保存圖片
img.save("output.png")   # 另存為 PNG 格式

說明:可以將圖片保存為不同格式,只需更改文件后綴。


圖像轉換
gray = img.convert("L")   # 轉為灰度圖
rgba = img.convert("RGBA") # 轉為含透明通道

說明:使用 convert()? 可以轉換圖片顏色模式。


圖像縮放和縮略圖
resized = img.resize((100, 100))   # 強制縮放為100x100thumb = img.copy()
thumb.thumbnail((100, 100))        # 縮略圖,保持比例

說明:resize()? 會強行變形,thumbnail()? 則保持原比例縮小。


裁剪圖像
box = (50, 50, 200, 200)      # 左、上、右、下坐標
cropped = img.crop(box)
cropped.show()

說明:裁剪區域的坐標單位為像素,左上角為原點 (0, 0)。


旋轉和翻轉
rotated = img.rotate(90)          # 順時針旋轉90°
flipped = img.transpose(Image.FLIP_LEFT_RIGHT)  # 水平翻轉

說明:rotate()? 默認逆時針,實際顯示是順時針;transpose()? 支持翻轉和旋轉。


疊加文字(繪圖)
from PIL import ImageDraw, ImageFontdraw = ImageDraw.Draw(img)
draw.text((10, 10), "Hello", fill="red")
img.show()

說明:使用 ImageDraw.Draw()? 可對圖像進行繪制,默認字體簡單,若需設置字體需加載 ImageFont?。


拼接圖片
img1 = Image.open("a.jpg")
img2 = Image.open("b.jpg")new_img = Image.new("RGB", (img1.width + img2.width, img1.height))
new_img.paste(img1, (0, 0))
new_img.paste(img2, (img1.width, 0))
new_img.show()

說明:通過創建新圖像并粘貼已有圖像,可以實現拼接。


獲取像素值和修改像素
pixel = img.getpixel((0, 0))    # 獲取坐標(0,0)處像素
img.putpixel((0, 0), (255, 0, 0)) # 修改為紅色像素(RGB 模式)

說明:適用于手動像素級操作,效率較低。


圖片轉 numpy 數組
import numpy as nparr = np.array(img)
print(arr.shape)  # 如:(高, 寬, 通道數)

說明:配合 NumPy 可以進行高效的圖像計算與分析。


numpy 數組轉圖片
new_img = Image.fromarray(arr)
new_img.show()

說明:Image.fromarray()? 可以把 NumPy 數組還原為圖像對象。


圖像格式轉換與壓縮
img.save("output.jpg", quality=85)  # 保存為 JPEG 并設置壓縮質量

說明:quality? 參數可控制 JPEG 圖像壓縮程度,范圍 1~95(默認是 75)。


檢查圖片是否損壞
try:img.verify()print("圖片無損壞")
except:print("圖片損壞")

說明:verify()? 方法可以驗證圖片文件是否完整有效。


創建純色圖像
new_img = Image.new("RGB", (200, 200), color="blue")
new_img.show()

說明:Image.new()? 可創建指定顏色和尺寸的新圖片。


opencv

OpenCV(Open Source Computer Vision Library) 是一個開源的計算機視覺庫,廣泛用于圖像處理、視頻分析、人臉識別等任務。Python 中使用時通過 cv2? 模塊操作,支持 NumPy 數組與圖像的高效互操作。

基本用法:

import cv2

讀取和顯示圖片
img = cv2.imread("a.jpg")       # 讀取圖像
cv2.imshow("Image", img)        # 顯示圖像窗口
cv2.waitKey(0)                  # 等待按鍵
cv2.destroyAllWindows()         # 關閉窗口

說明:OpenCV 使用 BGR? 而非 RGB?;必須調用 waitKey()? 才能顯示窗口。


保存圖片
cv2.imwrite("output.jpg", img)

說明:將圖像保存為文件,支持 jpg/png 等格式。


圖像尺寸和屬性
print(img.shape)     # (高, 寬, 通道數),例如 (400, 600, 3)
print(img.dtype)     # 圖像數據類型,例如 uint8

修改圖像尺寸
resized = cv2.resize(img, (200, 100))  # 寬200,高100

轉換顏色空間
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)   # 轉灰度圖
rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)     # BGR轉RGB

圖像裁剪與ROI
roi = img[100:200, 150:300]   # 裁剪區域:高100-200,寬150-300

說明:和 NumPy 一樣用切片操作,裁剪結果仍是圖像。


圖像繪圖(在圖上畫圖形)
cv2.rectangle(img, (50, 50), (150, 150), (0, 255, 0), 2)  # 綠色矩形
cv2.circle(img, (100, 100), 30, (255, 0, 0), -1)          # 藍色實心圓
cv2.line(img, (0, 0), (200, 200), (0, 0, 255), 3)         # 紅色直線

添加文字
cv2.putText(img, "Hello", (50, 50), cv2.FONT_HERSHEY_SIMPLEX,1, (255, 255, 255), 2)

說明:可以自定義字體、大小、顏色和粗細。


圖像濾波(模糊)
blur = cv2.GaussianBlur(img, (5, 5), 0)    # 高斯模糊
median = cv2.medianBlur(img, 5)           # 中值模糊

邊緣檢測
edges = cv2.Canny(img, 100, 200)   # 邊緣檢測

說明:兩個參數為低/高閾值。


圖像閾值處理(二值化)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

圖像按位操作(遮罩)
mask = np.zeros(img.shape[:2], dtype=np.uint8)
mask[100:200, 100:200] = 255
masked = cv2.bitwise_and(img, img, mask=mask)

攝像頭讀取(實時視頻)
cap = cv2.VideoCapture(0)  # 0代表默認攝像頭while True:ret, frame = cap.read()if not ret:breakcv2.imshow("Live", frame)if cv2.waitKey(1) == ord("q"):breakcap.release()
cv2.destroyAllWindows()

說明:按下 q? 鍵退出循環。


圖像通道操作
b, g, r = cv2.split(img)         # 拆分BGR通道
merged = cv2.merge([b, g, r])    # 合并通道

圖像疊加(加權合并)
blended = cv2.addWeighted(img1, 0.6, img2, 0.4, 0)

說明:將兩張圖按比例混合,適用于圖像融合、水印等。


輪廓檢測(基本)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(img, contours, -1, (0, 255, 0), 2)

保存視頻
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('out.avi', fourcc, 20.0, (640, 480))while True:ret, frame = cap.read()if not ret:breakout.write(frame)cv2.imshow('Recording', frame)if cv2.waitKey(1) == ord('q'):breakcap.release()
out.release()
cv2.destroyAllWindows()

復制與原地修改
img_copy = img.copy()
img_copy[0:100, 0:100] = 0   # 修改左上角為黑色,不影響原圖

任務一實踐

任務:

通過編寫腳本,處理DDXPlus數據集,將數據集release_train_patients中每個病人(案例)劃分為一個json文件

(1)release_train_patients

(2)release_evidences.json(里面含有代碼(E_91等)的映射關系)

(3)release_conditions.json(里面有每個疾病的具體信息)

劃分的json文件,要包含上述三個文件中的相應信息。

json文件命名格式participant_{i}.json

因為train數據集的病人比較多,劃分出200個病人的即可

├── data/
│   └── DDXPlus/
│       ├── release_evidences.json
│       ├── release_conditions.json
│       └── release_train_patients.csv
├── result/    ← 希望輸出的 json 文件保存到這里result/participants_output
├── split_ddxplus.py  ← 要運行的腳本
創建虛擬環境
python -m venv venv激活虛擬環境
.\.venv\Scripts\Activate.ps1安裝pandas庫
pip install pandas

在這里插入圖片描述

split_ddxplus.py腳本源碼學習

import json             # 導入json模塊,用于JSON數據的讀取和寫入
import os               # 導入os模塊,用于文件和目錄操作
import pandas as pd     # 導入pandas模塊,用于讀取和處理CSV文件# 設置基礎路徑,即數據文件所在目錄
base_path = 'data/DDXPlus'# 構造訓練數據CSV文件的完整路徑
train_file = os.path.join(base_path, 'release_train_patients.csv')# 構造證據JSON文件的完整路徑
evidence_file = os.path.join(base_path, 'release_evidences.json')# 構造病癥條件JSON文件的完整路徑
condition_file = os.path.join(base_path, 'release_conditions.json')# 設置結果輸出目錄
output_dir = 'result/participants_output'# 創建輸出目錄,如果目錄已存在則不會報錯
os.makedirs(output_dir, exist_ok=True)# 讀取訓練數據CSV文件,結果是pandas的DataFrame對象
train_df = pd.read_csv(train_file)# 以utf-8編碼打開證據JSON文件,讀取內容為Python對象(一般是list或dict)
with open(evidence_file, 'r', encoding='utf-8') as f:evidence_data = json.load(f)# 判斷evidence_data的類型,確保它是一個字典(方便后續按ID查找)
if isinstance(evidence_data, list):# 如果是列表,轉換為字典,鍵為每個證據的'id',值為該證據的完整信息evidence_map = {item['id']: item for item in evidence_data}
elif isinstance(evidence_data, dict):# 如果本來就是字典,直接賦值evidence_map = evidence_data
else:# 如果既不是list也不是dict,拋出異常提示格式不支持raise ValueError("release_evidences.json 格式不支持")# 以utf-8編碼打開條件JSON文件,讀取內容為Python對象
with open(condition_file, 'r', encoding='utf-8') as f:condition_data = json.load(f)# 同樣判斷condition_data類型,確保是字典格式
if isinstance(condition_data, list):# 如果是列表,轉換為字典,鍵為病癥id,值為病癥詳細信息condition_map = {item['id']: item for item in condition_data}
elif isinstance(condition_data, dict):# 直接賦值condition_map = condition_data
else:# 拋異常raise ValueError("release_conditions.json 格式不支持")# 遍歷訓練數據的前200個病人記錄(防止數據過多,控制處理數量)
for i in range(min(200, len(train_df))):# 通過iloc根據索引i選取DataFrame中的一行數據,返回Series對象row = train_df.iloc[i]# 解析該行中'evidence'字段的JSON字符串,轉換成Python對象try:# 先判斷'evidence'字段是否存在且不是空值,再用json.loads轉換if 'evidence' in row and pd.notna(row['evidence']):patient_evidences_raw = json.loads(row['evidence'])else:patient_evidences_raw = []except:# 如果解析失敗,則賦空列表,避免程序崩潰patient_evidences_raw = []# 同理解析'conditions'字段try:if 'conditions' in row and pd.notna(row['conditions']):patient_conditions_raw = json.loads(row['conditions'])else:patient_conditions_raw = []except:patient_conditions_raw = []# 從解析后的evidences列表中提取每條證據的id,過濾掉格式不對的數據evidence_ids = [e['id'] for e in patient_evidences_raw if isinstance(e, dict) and 'id' in e]# 確保patient_conditions_raw是列表類型,賦給condition_ids,否則賦空列表condition_ids = patient_conditions_raw if isinstance(patient_conditions_raw, list) else []# 根據id從證據字典中獲取對應證據詳細信息,忽略id不存在的情況evidence_details = [evidence_map[eid] for eid in evidence_ids if eid in evidence_map]# 根據id從條件字典中獲取對應條件詳細信息,忽略id不存在的情況condition_details = [condition_map[cid] for cid in condition_ids if cid in condition_map]# 將當前病人整行信息轉換為字典形式,方便一起存儲patient_info = row.to_dict()# 構造完整的病人數據結構,包括基本信息,證據詳情,條件詳情result = {'patient_info': patient_info,'evidence_details': evidence_details,'condition_details': condition_details}# 生成輸出文件名,例如 participant_0.jsonfilename = f'participant_{i}.json'# 拼接文件保存完整路徑filepath = os.path.join(output_dir, filename)# 以寫入模式打開文件,編碼為utf-8with open(filepath, 'w', encoding='utf-8') as f:# 將result字典轉換成格式化的JSON字符串寫入文件,確保中文正常顯示json.dump(result, f, ensure_ascii=False, indent=2)# 打印提示,表示當前病人數據已成功保存print(f"已保存:{filename}")
?

?

詳細分步解析
import json
import os
import pandas as pd
  • 導入 Python 標準庫中的 json? 用于 JSON 格式數據處理,os? 用于操作文件路徑和目錄,pandas? 用于處理 CSV 文件和表格數據。
# 設置路徑
base_path = 'data/DDXPlus'
train_file = os.path.join(base_path, 'release_train_patients.csv')
evidence_file = os.path.join(base_path, 'release_evidences.json')
condition_file = os.path.join(base_path, 'release_conditions.json')
  • ?base_path? 是數據集文件所在的根目錄。
  • 使用 os.path.join? 拼接得到訓練數據 CSV 文件的完整路徑 train_file?。
  • 同理,拼接得到 evidence_file? 和 condition_file? 的路徑,分別對應證據和病癥的 JSON 文件。
# 輸出目錄
output_dir = 'result/participants_output'
os.makedirs(output_dir, exist_ok=True)
  • 定義輸出結果保存目錄 output_dir?。
  • ?os.makedirs? 遞歸創建該目錄,如果目錄已存在則不會報錯(exist_ok=True?)。
# 讀取 CSV 數據
train_df = pd.read_csv(train_file)
  • pandas.read_csv? 讀取訓練數據 CSV 文件,存成一個 DataFrame 對象 train_df?,方便后續按行操作。
# 讀取 evidence JSON 數據
with open(evidence_file, 'r', encoding='utf-8') as f:evidence_data = json.load(f)
  • 以 UTF-8 編碼打開證據 JSON 文件,使用 json.load? 讀取成 Python 對象,賦值給 evidence_data?。
# 判斷 evidence_data 是不是 dict,不是就轉換為 dict
if isinstance(evidence_data, list):evidence_map = {item['id']: item for item in evidence_data}
elif isinstance(evidence_data, dict):evidence_map = evidence_data
else:raise ValueError("release_evidences.json 格式不支持")
  • 判斷 evidence_data? 的數據類型:

    • 如果是列表,則把每個證據的 id? 作為 key,證據對象作為 value,構建成字典 evidence_map? 方便快速查找。
    • 如果本身是字典,直接賦值給 evidence_map?。
    • 其它類型則拋出異常,提示格式不支持。
# 讀取 condition JSON 數據
with open(condition_file, 'r', encoding='utf-8') as f:condition_data = json.load(f)
  • 以 UTF-8 編碼打開疾病條件 JSON 文件,讀取為 Python 對象 condition_data?。
# 同樣處理 condition_data
if isinstance(condition_data, list):condition_map = {item['id']: item for item in condition_data}
elif isinstance(condition_data, dict):condition_map = condition_data
else:raise ValueError("release_conditions.json 格式不支持")
  • condition_data? 做同樣的判斷和轉換,確保最終 condition_map? 是字典,方便后續根據 ID 查找詳細信息。
# 處理前200個病人
for i in range(min(200, len(train_df))):row = train_df.iloc[i]
  • 循環遍歷訓練數據的前 200 條記錄(如果不足200條,就遍歷所有)。
  • ?train_df.iloc[i]? 按索引 i 獲取對應行數據,存到 row?,類型是 pandas Series。
    try:patient_evidences_raw = json.loads(row['evidence']) if 'evidence' in row and pd.notna(row['evidence']) else []except:patient_evidences_raw = []
  • 嘗試解析當前行的 'evidence'? 字段(應該是 JSON 字符串):

    • 如果字段存在且不是空值,使用 json.loads? 轉成 Python 對象。
    • 如果不存在或是空,賦空列表。
    • 若解析失敗(格式錯誤等),也賦空列表,避免程序崩潰。
    try:patient_conditions_raw = json.loads(row['conditions']) if 'conditions' in row and pd.notna(row['conditions']) else []except:patient_conditions_raw = []
  • 同理,嘗試解析當前行的 'conditions'? 字段,處理方法和上一段相同,得到原始條件列表 patient_conditions_raw?。
    # 提取 IDevidence_ids = [e['id'] for e in patient_evidences_raw if isinstance(e, dict) and 'id' in e]condition_ids = patient_conditions_raw if isinstance(patient_conditions_raw, list) else []
  • patient_evidences_raw? 中篩選出每個證據的 id? 字段,生成 evidence_ids? 列表。
  • ?patient_conditions_raw? 如果是列表則直接賦值給 condition_ids?,否則賦空列表(保險處理)。
    # 獲取詳細信息evidence_details = [evidence_map[eid] for eid in evidence_ids if eid in evidence_map]condition_details = [condition_map[cid] for cid in condition_ids if cid in condition_map]
  • 根據 evidence_ids? 和 condition_ids?,從之前構建的映射字典 evidence_map? 和 condition_map? 中取對應詳細信息,生成詳細信息列表。
    # 構建結果patient_info = row.to_dict()
  • 將當前患者行數據 row? 轉成字典,方便和證據、條件信息合并,構成完整數據結構。
    result = {'patient_info': patient_info,'evidence_details': evidence_details,'condition_details': condition_details}
  • 構造最終輸出的字典結構,包含患者信息,證據詳情和條件詳情三個部分。
    # 保存文件filename = f'participant_{i}.json'filepath = os.path.join(output_dir, filename)with open(filepath, 'w', encoding='utf-8') as f:json.dump(result, f, ensure_ascii=False, indent=2)
  • 構造輸出文件名,格式是 participant_0.json?、participant_1.json? 等。
  • 拼接成完整保存路徑。
  • 以 UTF-8 編碼寫入 JSON 文件,參數 ensure_ascii=False? 保持中文顯示,indent=2? 格式化縮進方便閱讀。
    print(f"已保存:{filename}")
  • 控制臺打印提示,告訴用戶當前第 i 個患者信息已保存完成,方便調試和跟蹤進度。

任務二實踐

任務:

處理vaihingen數據集,將每個大圖像劃分并轉換為512**512的jpg格式圖像,不足512** 512的部分用黑色像素填充,圖像和其標簽要一起進行處理
項目根目錄/
├── data/
│   └── vaihingen/
│       ├── image/          ← 存放原始圖像(.tif)
│       └── label/          ← 存放對應標簽圖(.tif)
├── result/
│   └── new_vaihingen/
│       ├── new_image/          ← 保存裁剪后的圖像(.jpg)
│       └── new_label/          ← 保存裁剪后的標簽(.png)
├── split_vaihingen.py       ← 運行腳本
pip install opencv-python tqdm numpy

在這里插入圖片描述

split_vaihingen.py腳本源碼學習

import os
import cv2
import numpy as np
from glob import glob
from tqdm import tqdmtile_size = 512  # 裁剪窗口大小,512x512像素# 設置輸入路徑,分別是彩色原圖和灰度標簽圖目錄
image_dir = 'data/vaihingen/image'
label_dir = 'data/vaihingen/label'# 設置輸出路徑,分別保存裁剪后的圖像和標簽
out_img_dir = 'result/new_vaihingen/new_image'
out_lbl_dir = 'result/new_vaihingen/new_label'os.makedirs(out_img_dir, exist_ok=True)  # 自動創建圖像輸出目錄
os.makedirs(out_lbl_dir, exist_ok=True)  # 自動創建標簽輸出目錄# 獲取所有圖像和標簽路徑,并排序保證對應關系
image_paths = sorted(glob(os.path.join(image_dir, '*.tif')))
label_paths = sorted(glob(os.path.join(label_dir, '*_noBoundary.tif')))assert len(image_paths) == len(label_paths), "圖像和標簽數量不一致"  # 確保一一對應# 遍歷所有圖像-標簽對
for img_path, lbl_path in tqdm(zip(image_paths, label_paths), total=len(image_paths), desc='正在處理'):image = cv2.imread(img_path, cv2.IMREAD_COLOR)  # 讀取彩色圖if image is None:print(f"[錯誤] 無法讀取圖像文件: {img_path}")continuelabel = cv2.imread(lbl_path, cv2.IMREAD_GRAYSCALE)  # 讀取灰度標簽if label is None:print(f"[錯誤] 無法讀取標簽文件: {lbl_path}")continueh, w = image.shape[:2]  # 獲取圖像高寬# 從文件名中提取“area_數字”作為命名前綴basename = os.path.splitext(os.path.basename(img_path))[0]  # 例如 top_mosaic_09cm_area1area_name = "area_" + basename.split("area")[-1]  # 結果如 area_1# 按512像素步長遍歷圖像坐標進行裁剪for y in range(0, h, tile_size):for x in range(0, w, tile_size):tile_img = image[y:y+tile_size, x:x+tile_size]  # 裁剪圖像塊tile_lbl = label[y:y+tile_size, x:x+tile_size]  # 裁剪對應標簽塊# 如果標簽塊為空(無內容),跳過該塊if tile_lbl is None or tile_lbl.size == 0:print(f"[警告] tile_lbl 是空的,跳過該塊。坐標: ({x}, {y}) in {area_name}")continue# 判斷圖像塊是否足夠512*512,不夠則用黑色填充if tile_img.shape[0] < tile_size or tile_img.shape[1] < tile_size:pad_img = np.zeros((tile_size, tile_size, 3), dtype=np.uint8)  # 黑色背景圖像pad_lbl = np.zeros((tile_size, tile_size), dtype=np.uint8)     # 黑色背景標簽pad_img[:tile_img.shape[0], :tile_img.shape[1]] = tile_img   # 復制原圖內容到左上角pad_lbl[:tile_lbl.shape[0], :tile_lbl.shape[1]] = tile_lbl   # 復制標簽內容tile_img = pad_img  # 替換為填充后的圖像tile_lbl = pad_lbl  # 替換為填充后的標簽# 生成輸出文件名,含坐標信息確保唯一性img_name = f"{area_name}_{y}_{x}.jpg"lbl_name = f"{area_name}_{y}_{x}.png"# 保存裁剪好的圖像和標簽cv2.imwrite(os.path.join(out_img_dir, img_name), tile_img)cv2.imwrite(os.path.join(out_lbl_dir, lbl_name), tile_lbl)
詳細分步解析
import os
import cv2
import numpy as np
from glob import glob
from tqdm import tqdm
  • 導入所需庫:os?處理路徑,cv2?處理圖像,numpy?做數組和填充,glob?匹配文件,tqdm?顯示進度條。
tile_size = 512
  • 定義裁剪小塊的尺寸為512×512像素。
image_dir = 'data/vaihingen/image'
label_dir = 'data/vaihingen/label'
  • 指定輸入路徑,分別是原始彩色大圖和對應的標簽灰度圖文件夾。
out_img_dir = 'result/new_vaihingen/new_image'
out_lbl_dir = 'result/new_vaihingen/new_label'
  • 指定輸出路徑,用于保存裁剪后的小圖像和對應標簽。
os.makedirs(out_img_dir, exist_ok=True)
os.makedirs(out_lbl_dir, exist_ok=True)
  • 自動創建輸出文件夾,如果已經存在則不會報錯。
image_paths = sorted(glob(os.path.join(image_dir, '*.tif')))
label_paths = sorted(glob(os.path.join(label_dir, '*_noBoundary.tif')))
  • 利用glob?獲取所有符合后綴的文件路徑,并排序,確保圖像和標簽順序對應。
assert len(image_paths) == len(label_paths), "圖像和標簽數量不一致"
  • 確保圖像和標簽數量匹配,一對一對應。
for img_path, lbl_path in tqdm(zip(image_paths, label_paths), total=len(image_paths), desc='正在處理'):
  • 遍歷每對圖像和標簽路徑,用tqdm?顯示進度條。
    image = cv2.imread(img_path, cv2.IMREAD_COLOR)if image is None:print(f"[錯誤] 無法讀取圖像文件: {img_path}")continue
  • 讀取彩色圖像,如果讀取失敗則輸出錯誤并跳過。
    label = cv2.imread(lbl_path, cv2.IMREAD_GRAYSCALE)if label is None:print(f"[錯誤] 無法讀取標簽文件: {lbl_path}")continue
  • 讀取灰度標簽圖,失敗則報錯跳過。
    h, w = image.shape[:2]
  • 獲取當前圖像的高(行數)和寬(列數)。
    basename = os.path.splitext(os.path.basename(img_path))[0]area_name = "area_" + basename.split("area")[-1]
  • 解析圖像文件名,提取area_數字?作為命名前綴,方便區分圖像來源。
    for y in range(0, h, tile_size):for x in range(0, w, tile_size):
  • 以512步長在圖像寬高方向上滑動,遍歷每個裁剪窗口的左上角坐標。
            tile_img = image[y:y+tile_size, x:x+tile_size]tile_lbl = label[y:y+tile_size, x:x+tile_size]
  • 根據當前坐標裁剪圖像塊和對應標簽塊,大小通常是512×512,但邊緣可能小于512。
            if tile_lbl is None or tile_lbl.size == 0:print(f"[警告] tile_lbl 是空的,跳過該塊。坐標: ({x}, {y}) in {area_name}")continue
  • 如果標簽塊為空(可能是超出邊界或沒有內容),打印警告并跳過,避免無效數據。
            if tile_img.shape[0] < tile_size or tile_img.shape[1] < tile_size:pad_img = np.zeros((tile_size, tile_size, 3), dtype=np.uint8)pad_lbl = np.zeros((tile_size, tile_size), dtype=np.uint8)pad_img[:tile_img.shape[0], :tile_img.shape[1]] = tile_imgpad_lbl[:tile_lbl.shape[0], :tile_lbl.shape[1]] = tile_lbltile_img = pad_imgtile_lbl = pad_lbl
  • 判斷裁剪塊是否小于512×512(通常在圖像邊緣),如果是:

    • 創建全黑的512×512空白圖像和標簽圖;
    • 把原始裁剪塊數據復制到黑色背景的左上角;
    • 這樣確保所有輸出塊尺寸統一為512×512。
            img_name = f"{area_name}_{y}_{x}.jpg"lbl_name = f"{area_name}_{y}_{x}.png"
  • 根據area_數字?和裁剪左上角坐標,生成唯一文件名,方便后續對應。
            cv2.imwrite(os.path.join(out_img_dir, img_name), tile_img)cv2.imwrite(os.path.join(out_lbl_dir, lbl_name), tile_lbl)
  • 將裁剪并(如需)填充后的圖像塊和標簽塊保存為文件,格式分別是jpg和png。

認識數據增強

數據增強(Data Augmentation)是對原始訓練數據進行各種變換操作,生成更多的“新”樣本,從而擴充訓練集。通過讓模型見到更多樣化的訓練樣本,減少過擬合,提高模型在真實環境中的表現。


常見的數據增強方法

幾何變換(Geometric Transformations)

  • 旋轉(Rotation) :將圖像順時針或逆時針旋轉一定角度(如90度、180度、任意角度)。
  • 翻轉(Flip) :水平翻轉(左右鏡像)或垂直翻轉(上下鏡像)。
  • 平移(Translation) :圖像整體上下左右移動若干像素。
  • 縮放(Scaling) :放大或縮小圖像尺寸。
  • 裁剪(Crop) :隨機裁剪圖像的一部分,作為新樣本。
  • 仿射變換(Affine Transform) :包括旋轉、縮放、平移和剪切等組合變換。

顏色變換(Color Transformations)

  • 調整亮度(Brightness) :調節圖像整體亮度。
  • 調整對比度(Contrast) :增強或減弱圖像對比度。
  • 調整飽和度(Saturation) :改變圖像顏色的鮮艷度。
  • 顏色抖動(Color Jitter) :隨機微調亮度、對比度、飽和度等。

添加噪聲(Noise Injection)

  • 高斯噪聲(Gaussian Noise) :在像素值中加入高斯分布噪聲。
  • 椒鹽噪聲(Salt-and-Pepper Noise) :隨機像素被替換為極端黑白值。

模糊和銳化(Blurring and Sharpening)

  • 高斯模糊(Gaussian Blur) :圖像平滑處理,減弱細節。
  • 銳化(Sharpening) :增強邊緣和細節。

復雜增強技術(Advanced Techniques)

  • Cutout:隨機遮擋圖像的一部分區域,模擬遮擋。
  • Mixup:將兩張圖像按一定比例混合,同時混合標簽。
  • CutMix:剪切一塊圖像并粘貼到另一張圖像上,同時對應標簽也按比例調整。

數據增強的作用
  • 增加訓練數據多樣性,降低過擬合風險。
  • 提升模型的泛化能力,使其在各種變化環境下表現更穩健。
  • 彌補樣本數量不足,尤其在數據采集困難或成本高時尤為重要。

Python中常用的數據增強庫
  • Albumentations:功能豐富且高效的圖像增強庫。
  • imgaug:支持復雜的序列增強操作。
  • torchvision.transforms:PyTorch框架內置的常用增強函數。
  • Keras ImageDataGenerator:Keras內置的實時圖像增強工具。

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

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

相關文章

力扣面試150題--顛倒二進制位

Day 89 題目描述思路 二進制的算法&#xff0c;將十進制轉化為二進制&#xff0c;有一點需要注意&#xff0c;直接采取庫函數轉化為二進制再反轉會出現問題&#xff08;這也是為什么我要補0的原因&#xff09;&#xff0c;因為轉化過去不滿足32位的二進制&#xff0c;前面不會當…

【ResNet50圖像分類部署至RK3588】模型訓練→轉換RKNN→開發板部署

已在GitHub開源與本博客同步的ResNet50v2_RK3588_Classificationt項目&#xff0c;地址&#xff1a;https://github.com/A7bert777/ResNet50v2_RK3588_Classification 詳細使用教程&#xff0c;可參考README.md或參考本博客第八章 模型部署 文章目錄一、項目回顧二、模型選擇介…

C# _泛型

目錄 泛型是什么? 泛型的主要優勢 創建一個泛型類 泛型方法 泛型是什么? 泛型是通過參數化來實現同一份代碼上操作多種數據類型 利用參數類型將參數的類型抽象化 從而實現靈活的復用 總結: 通過泛型可以實現在同一份代碼上操作多種數據類型的邏輯 將類和類中的成員定義…

Vue路由鉤子完全指南

Vue.js中的路由導航鉤子&#xff08;Navigation Guards&#xff09;主要用于在路由導航過程中進行攔截和處理&#xff0c;確保訪問控制和狀態管理。以下是主要分類及使用方法&#xff1a; 1. 全局鉤子函數 作用于整個路由實例&#xff0c;需在路由配置外定義&#xff1a; befor…

RAGFlow 登錄界面點擊登錄無反應,控制臺報錯 502 Bad Gateway 解決方法

遇到的問題 在使用RAGFlow的時候&#xff0c;登錄不進去&#xff0c;但是之前能登錄。 還出現了輸入地址直接進入工作界面&#xff0c;但是進行不了任何操作的bug&#xff1b;以及無法上傳文檔的問題&#xff08;其實都是因為沒登錄&#xff09;。 登陸界面報錯如圖顯示。 …

數據結構第3問:什么是線性表?

線性表 線性表由具有相同數據類型的n個元素構成&#xff0c;這些元素之間存在一一對應的線性關系。其中n為表長&#xff0c;當n0的時候線性表是一個空表。簡單來說&#xff0c;線性表中的元素排列成一條線&#xff0c;每個元素最多有一個直接的前驅和后繼&#xff08;除第一個和…

常見CMS 靶場復現

一、wordpass1.修改模版文件getshell搭建網站登錄網站后臺更改網站模版的相關文件寫入一句話木馬憑借路徑訪問/wp-content/themes/twentyfifteen/404.php/?aphpinfo();2.上傳夾帶木馬的主題getshell外觀-->主題-->添加-->上傳-->瀏覽-->安裝-->訪問木馬文件…

Elasticsearch - 倒排索引原理和簡易實現

倒排索引的功能設計倒排索引&#xff08;Inverted Index&#xff09;是一種高效的數據結構&#xff0c;常用于全文搜索和信息檢索系統。它的核心思想是將文檔中每個關鍵字&#xff08;term&#xff09;與包含該關鍵字的文檔列表進行映射。以下是實現倒排索引功能的設計步驟和代…

C#開發的Panel里控件拖放例子 - 開源研究系列文章

上次寫了Panel的分頁滾動控件( C#開發的Panel滾動分頁控件&#xff08;滑動版&#xff09; - 開源研究系列文章 - Lzhdims Fashion - 博客園 )&#xff0c;但是主要是想寫一個Panel里控件拖放的效果&#xff0c;然后分頁控件用于Panel里控件的分頁。此文這次寫的是控件拖放效果…

Thinkph6中常用的驗證方式實例

我們在使用thinkphp6中的數據驗證時&#xff0c;如果使用不多的話&#xff0c;會經常遇到校驗不對&#xff0c;在這個小問題上折騰很多&#xff0c;索引就不用了。我還不如直接寫if條件來的迅捷&#xff01;&#xff01;下面把常見的校驗方法進行一下整理&#xff1a;protected…

分享一個FPGA寄存器接口自動化工具

FPGA模塊越寫越多&#xff0c;規范性和可移植性卻堪憂。要是有一個工具可以根據模塊接口描述文件生成verilog和c頭文件就好了。苦苦搜尋找到了幾款免費的工具&#xff0c;SystemRDL、cheby和rggen。筆者學習了下cheby和reksio&#xff0c;reksio是gui版的cheby&#xff0c;這是…

小程序中事件對象的屬性與方法

在小程序中&#xff0c;事件處理函數的參數為事件對象&#xff08;通常命名為 e&#xff09;&#xff0c;包含了事件相關的詳細信息&#xff08;如事件類型、觸發元素、傳遞的數據等&#xff09;。事件對象的屬性和方法因事件類型&#xff08;如點擊、輸入、觸摸等&#xff09;…

使用寶塔“PostgreSQL管理器”安裝的PostgreSQL,如何設置遠程連接?

安裝 PostgreSQL 使用寶塔“PostgreSQL管理器”安裝PostgreSQL&#xff0c;版本可以根據自己的需求來選擇&#xff0c;我這里使用的是16.1 創建數據庫 根據下圖所示步驟創建數據庫&#xff0c;其中 “訪問權限”一定要選擇“所有人”啟用遠程連接設置允許所有 IP 連接 listen_a…

論文:M矩陣

M矩陣是線性代數中的一個概念&#xff0c;它是一種特殊類型的矩陣&#xff0c;具有以下性質&#xff1a;非負的非對角線元素&#xff1a;矩陣的所有非對角線元素都是非負的&#xff0c;即對于矩陣MMM中的任意元素mijm_{ij}mij?&#xff0c;當i≠ji\neq jij時&#xff0c;有m…

跳躍表可視化深度解析:動態演示數據結構核心原理

跳躍表可視化深度解析&#xff1a;動態演示數據結構核心原理 一、跳躍表基礎概念與核心優勢 跳躍表&#xff08;SkipList&#xff09;是一種基于多層索引鏈表的數據結構&#xff0c;通過概率平衡實現高效的插入、刪除和查找操作。其核心優勢體現在&#xff1a; ?時間復雜度優…

《Sentinel服務保護實戰:控制臺部署與SpringCloud集成指南》

sentinel 介紹 Sentinel是阿里巴巴開源的一款服務保護框架&#xff0c;目前已經加入SpringCloudAlibaba中。官方網站&#xff1a; home | Sentinel Sentinel 的使用可以分為兩個部分: 核心庫&#xff08;Jar包&#xff09;&#xff1a;不依賴任何框架/庫&#xff0c;能夠運行…

IBM Watsonx BI:AI賦能的下一代商業智能平臺

產品概覽 IBM Watsonx BI 是基于 watsonx 企業級 AI 與數據平臺 構建的智能分析解決方案&#xff0c;專為現代化企業打造。它深度融合人工智能技術&#xff0c;突破傳統 BI 工具的限制&#xff0c;通過自動化數據洞察、自然語言交互和預測分析&#xff0c;幫助企業在復雜數據環…

Python實現GO鵝優化算法優化GBRT漸進梯度回歸樹回歸模型項目實戰

說明&#xff1a;這是一個機器學習實戰項目&#xff08;附帶數據代碼文檔&#xff09;&#xff0c;如需數據代碼文檔可以直接到文章最后關注獲取 或者私信獲取。 1.項目背景 隨著大數據和人工智能技術的快速發展&#xff0c;回歸預測在金融、氣象、能源等多個領域中扮演著至關…

深度學習計算(深度學習-李沐-學習筆記)

層和塊 單一輸出的線性模型&#xff1a;單個神經網絡 &#xff08;1&#xff09;接受一些輸入&#xff1b; &#xff08;2&#xff09;生成相應的標量輸出&#xff1b; &#xff08;3&#xff09;具有一組相關 參數&#xff08;parameters&#xff09;&#xff0c;更新這些參數…

leetcode熱題——搜索二維矩陣Ⅱ

目錄 搜索二維矩陣Ⅱ 題目描述 題解 解法一&#xff1a;暴力搜索 C 代碼實現 復雜度分析 解法二&#xff1a;二分查找 C 代碼實現 復雜度分析 解法三&#xff1a;Z字形查找 算法核心思想 算法步驟詳解 C 代碼實現 復雜度分析 搜索二維矩陣Ⅱ 題目描述 編寫一個…