MATLAB的數據處理
1. 數據導入與導出
(1) 從文件讀取數據
- Excel 文件:
data = readtable('data.xlsx'); % 讀取為表格(Table)
- CSV 文件:
data = readtable('data.csv'); % 自動處理表頭和分隔符
- 文本文件:
data = load('data.txt'); % 數值數據直接加載為矩陣
(2) 導出數據到文件
- 保存為 Excel:
writetable(data, 'output.xlsx');
- 保存為 CSV:
writetable(data, 'output.csv');
2. 數據清洗與預處理
(1) 處理缺失值
1>查找缺失值:ismissing(data)
missingValues = ismissing(data); % 返回邏輯矩陣標記缺失值(NaN 或空字符)
- 功能:檢測
data
(可以是數組、表格、時間表等)中的缺失值,生成一個與data
維度相同的 邏輯矩陣(logical matrix
)。 - 輸出規則:
missingValues
中true
(1)表示對應位置是缺失值。false
(0)表示該位置數據正常。
支持的缺失值類型
- 數值型數據:
NaN
(Not a Number)。 - 時間型數據:
NaT
(Not a Time)。 - 字符串/字符數據:空字符串
""
(字符串數組)或<missing>
。 - 分類數據:
<undefined>
。 - 表格/時間表:自動識別各列的缺失值類型。
示例
假設 data
是一個表格:
ID | Age | Status |
---|---|---|
1 | 25 | “Complete” |
2 | NaN | “” |
3 | 30 | “” |
執行 missingValues = ismissing(data)
后,結果如下:
ID | Age | Status |
---|---|---|
0 | 0 | 0 |
0 | 1 | 1 |
0 | 0 | 1 |
2> 填充缺失值:fillmissing
代碼作用
data.Age = fillmissing(data.Age, 'constant', mean(data.Age, 'omitnan')); % 用均值填充
- 功能:將
data.Age
列中的缺失值(NaN
)填充為該列的均值(忽略缺失值計算)。 - 參數解析:
data.Age
:待填充的列(數值型向量)。'constant'
:填充方式為“常量填充”,即用固定值替換缺失值。mean(data.Age, 'omitnan')
:計算data.Age
列的均值時忽略NaN
值。
關鍵步驟
-
計算均值:
avg = mean(data.Age, 'omitnan'); % 忽略 NaN 計算均值
- 假設
data.Age = [25, NaN, 30]
,則avg = (25 + 30)/2 = 27.5
。
- 假設
-
填充缺失值:
data.Age = fillmissing(data.Age, 'constant', avg);
- 原始數據:
[25, NaN, 30]
→ 填充后:[25, 27.5, 30]
。
- 原始數據:
其他填充方法
- 插值填充:
fillmissing(data.Age, 'linear')
(線性插值)。 - 鄰近值填充:
fillmissing(data.Age, 'previous')
(用前一個有效值填充)。
注意事項
-
確保數據類型一致:
fillmissing
的填充值必須與列的數據類型兼容(例如,數值列用數值填充,字符串列用字符串填充)。
-
處理全缺失列:
- 若某列全部為
NaN
,mean(..., 'omitnan')
會返回NaN
,導致填充無效。需額外處理:if all(isnan(data.Age))data.Age = zeros(size(data.Age)); % 用0填充全缺失列 end
- 若某列全部為
-
分類變量處理:
- 分類數據(如
'Male'
,'Female'
)需用眾數填充:modeGender = mode(data.Gender, 'omitnan'); data.Gender = fillmissing(data.Gender, 'constant', modeGender);
- 分類數據(如
完整示例
原始數據
Age |
---|
25 |
NaN |
30 |
執行代碼后
Age |
---|
25 |
27.5 |
30 |
總結
ismissing
:精準定位數據中的缺失值,生成邏輯掩碼。fillmissing
:靈活填充缺失值,支持均值、插值、鄰近值等方法。- 核心技巧:結合
ismissing
的檢測結果,選擇合適策略清洗數據,確保后續分析可靠性。
(2) 數據篩選
- 按條件篩選行:
highScores = data(data.Score > 90, :); % 篩選 Score 列大于90的行
- 選擇特定列:
selectedData = data(:, {'Name', 'Age'}); % 選擇 Name 和 Age 列
(3) 數據轉換
涵蓋 類型轉換 和 分類數據編碼 的核心操作。
一、類型轉換:data.Age = double(data.Age);
1. 作用與原理
- 目標:將
data.Age
列的數據類型轉換為 雙精度浮點數(double
)。 - 適用場景:
- 原始數據可能是整數(
int
)、字符(char
)或其他類型。 - 需要統一數值類型以確保計算精度(例如參與科學計算或統計分析)。
- 原始數據可能是整數(
2. 示例說明
原始數據
假設 data.Age
原本是整數類型(int32
):
data = table([25; 30; 28], {'Male'; 'Female'; 'Male'}, 'VariableNames', {'Age', 'Gender'});
disp(class(data.Age)); % 輸出 'int32'
原始數據
Age (double) | Gender |
---|---|
25 | Male |
30 | Female |
28 | Male |
轉換代碼
data.Age = double(data.Age); % 轉換為雙精度浮點數
disp(class(data.Age)); % 輸出 'double'
轉換后數據
Age (double) | Gender |
---|---|
25.0 | Male |
30.0 | Female |
28.0 | Male |
3. 常見類型轉換函數
函數 | 作用 | 示例 |
---|---|---|
double() | 轉為雙精度浮點數 | x = double(int32(5)) → 5.0 |
single() | 轉為單精度浮點數 | x = single(3.14) |
int32() | 轉為32位整數 | x = int32(10.7) → 10 |
string() | 轉為字符串數組 | x = string(123) → "123" |
cellstr() | 轉為字符向量元胞數組 | x = cellstr("Text") → {'Text'} |
4. 注意事項
- 精度丟失:將浮點數轉換為整數時,小數部分會被截斷(非四舍五入)。
x = 3.9; y = int32(x); % y = 3
- 數據溢出:超出目標類型范圍的轉換會引發錯誤或產生意外值。
x = 500; y = int8(x); % int8 范圍是 [-128, 127],y = 127(溢出)
分類數據編碼:data.Gender = categorical(data.Gender);
1. 作用與原理
- 目標:將字符或字符串數據轉換為 分類變量(
categorical
)。 - 優勢:
- 節省內存:分類變量內部存儲為整數索引,而非重復的字符串。
- 高效操作:支持快速分組統計、排序、篩選。
- 語義清晰:保留原始標簽,方便可視化與分析。
2. 示例說明
原始數據
假設 data.Gender
是字符串數組:
data.Gender = ["Male"; "Female"; "Male"; "Female"];
disp(class(data.Gender)); % 輸出 'string'
注意:一定要轉換為categorical類型的數據
轉換代碼
data.Gender = categorical(data.Gender); % 轉換為分類變量
disp(class(data.Gender)); % 輸出 'categorical'
disp(categories(data.Gender)); % 輸出 {'Female', 'Male'}
轉換后數據
Gender (categorical) |
---|
Male |
Female |
Male |
Female |
3. 分類變量的核心操作
(1) 統計頻數
counts = countcats(data.Gender); % 輸出 [2; 2](Female:2, Male:2)
(2) 排序數據
sortedData = sortrows(data, 'Gender'); % 按分類順序排序(默認字母順序)
(3) 合并類別
% 將 'Male' 和 'Female' 合并為 'Other'
data.Gender = mergecats(data.Gender, {'Male', 'Female'}, 'Other');
disp(categories(data.Gender)); % 輸出 {'Other'}
(4) 處理缺失值
% 添加缺失值并填充
data.Gender(2) = missing; % 設置為 <undefined>
data.Gender = addcats(data.Gender, 'Unknown'); % 添加新類別
data.Gender(isundefined(data.Gender)) = 'Unknown'; % 填充缺失
4. 分類變量的優勢對比
操作 | 字符串數組 | 分類變量 |
---|---|---|
內存占用 | 高(存儲所有字符) | 低(存儲整數索引) |
分組統計速度 | 慢 | 快 |
支持自定義類別順序 | 不支持 | 支持(有序分類) |
三、綜合應用場景
場景:數據預處理流程
% 步驟1:讀取數據
data = readtable('survey_data.csv');% 步驟2:類型轉換(Age列轉為double)
data.Age = double(data.Age);% 步驟3:分類編碼(Gender列轉為分類變量)
data.Gender = categorical(data.Gender);% 步驟4:處理缺失值(用眾數填充Gender)
modeGender = mode(data.Gender, 'omitnan');
data.Gender = fillmissing(data.Gender, 'constant', modeGender);% 步驟5:保存處理后的數據
writetable(data, 'cleaned_survey_data.csv');
四、注意事項
- 類型轉換前檢查數據:
- 確保轉換后的類型適合后續分析(例如日期數據應轉為
datetime
)。
- 確保轉換后的類型適合后續分析(例如日期數據應轉為
- 分類變量的順序:
- 默認按字母順序排列,可通過
'Ordinal', true
指定邏輯順序。
- 默認按字母順序排列,可通過
- 缺失值處理:
- 分類變量中的缺失值顯示為
<undefined>
,需用addcats
和fillmissing
處理。
- 分類變量中的缺失值顯示為
總結
- 類型轉換:確保數據格式統一,滿足計算需求。
- 分類編碼:提升處理離散標簽數據的效率和可讀性。
- 核心函數:
double()
,categorical()
,countcats()
,mergecats()
。
3. 數據分析與統計
一、聚合統計
1. 分組統計:groupsummary
功能:按指定分組變量對數據進行分組,并計算統計量(如均值、總和、標準差等)。
語法
groupStats = groupsummary(data, groupVars, method, dataVars)
data
:輸入表格(table
)。groupVars
:分組變量(列名或列索引),支持單列或多列。method
:統計方法(如'mean'
,'sum'
,'std'
)。dataVars
:需要統計的數據列(列名或列索引)。
示例 1:按性別計算平均分
% 創建示例數據
data = table({'Male'; 'Female'; 'Male'; 'Female'}, [85; 92; 78; 88], 'VariableNames', {'Gender', 'Score'});% 按性別分組計算平均分
groupStats = groupsummary(data, 'Gender', 'mean', 'Score');
輸出結果:
Gender | GroupCount | mean_Score |
---|---|---|
Female | 2 | 90 |
Male | 2 | 81.5 |
示例 2:多分組變量與多統計方法
% 按性別和部門分組,計算銷售額的總和和均值
groupStats = groupsummary(data, {'Gender', 'Dept'}, {'sum', 'mean'}, 'Sales');
2. 交叉分析:crosstab
功能:生成交叉頻數表,統計兩個或多個分類變量的組合頻數。
語法
[table, chi2, p] = crosstab(var1, var2, ...)
var1, var2
:分類變量(向量或分類數組)。table
:交叉頻數表。chi2
:卡方檢驗統計量。p
:p 值(檢驗變量獨立性的顯著性)。
示例:性別與部門的交叉分析
% 創建示例數據
gender = categorical({'Male'; 'Female'; 'Male'; 'Female'});
dept = categorical({'IT'; 'HR'; 'IT'; 'HR'});% 生成交叉表
[counts, ~, ~] = crosstab(gender, dept);
disp(counts);
輸出:
HR | IT | |
---|---|---|
Female | 2 | 0 |
Male | 0 | 2 |
二、數值計算
1. 矩陣運算:cov
(協方差矩陣)
功能:計算數據列之間的協方差矩陣,反映變量間的線性相關性。
語法
covMatrix = cov(data)
data
:數值矩陣或表格中的數值列。covMatrix
:對稱矩陣,對角線為方差,非對角線為協方差。
示例:計算協方差矩陣
% 提取表格中的數值列(第2到5列)
numericData = data{:, 2:5};% 計算協方差矩陣
covariance = cov(numericData);
disp(covariance);
協方差解讀:
- 正值:變量同向變化。
- 負值:變量反向變化。
- 絕對值大小:表示相關性強度。
2. 自定義函數應用:arrayfun
功能:對數組的每個元素應用自定義函數,避免顯式循環。
語法
output = arrayfun(func, array)
func
:函數句柄(如@(x) x + 5
)。array
:輸入數組。output
:與輸入數組同維度的結果。
示例:所有分數加5
% 定義分數列
data.Score = [85; 92; 78; 88];% 對每個分數加5
data.AdjustedScore = arrayfun(@(x) x + 5, data.Score);
輸出:
Score | AdjustedScore |
---|---|
85 | 90 |
92 | 97 |
78 | 83 |
88 | 93 |
對比向量化操作:
% 更高效的向量化寫法
data.AdjustedScore = data.Score + 5;
三、綜合應用場景
場景:銷售數據分析
% 步驟1:讀取數據
data = readtable('sales_data.csv');% 步驟2:按地區和產品類別分組,計算總銷售額和平均利潤
groupStats = groupsummary(data, {'Region', 'Product'}, {'sum', 'mean'}, {'Sales', 'Profit'});% 步驟3:生成地區和銷售員的交叉表
[counts, ~, ~] = crosstab(data.Region, data.Salesperson);% 步驟4:計算銷售額與利潤的協方差
covMatrix = cov(data{:, {'Sales', 'Profit'}});% 步驟5:調整銷售額(所有值乘以1.1)
data.AdjustedSales = arrayfun(@(x) x * 1.1, data.Sales);
四、注意事項
-
數據類型一致性:
- 聚合統計和交叉分析要求分組變量為分類變量或可離散化的數值。
- 協方差計算需確保輸入為數值矩陣。
-
缺失值處理:
groupsummary
默認忽略缺失值,但需提前確認數據完整性。crosstab
會將缺失值單獨列為一類(<undefined>
)。
-
性能優化:
- 優先使用向量化操作(如
data.Score + 5
)替代arrayfun
,提升效率。 - 對大型數據,避免在循環中頻繁操作表格,可轉換為矩陣處理。
- 優先使用向量化操作(如
五、擴展函數推薦
函數 | 作用 | 示例 |
---|---|---|
grpstats | 分組統計(類似 groupsummary ) | grpstats(data, group, 'mean') |
varfun | 對表格列應用函數 | varfun(@mean, data) |
corrcoef | 計算相關系數矩陣 | corrcoef(data{:, 2:5}) |
pivot | 生成透視表 | pivot(data, Rows='Gender') |
生命如同寓言,其價值不在于長短,而在于內容。 —塞涅卡