在資料分析的叢林中,資料清理如同披荊斬棘,是確保資料品質的關鍵步驟。Pandas 提供了強大的工具,如同鋒利的刀刃,能有效處理缺失值和重複資料,讓資料分析師得以在乾淨的資料上建立可靠的分析結果。本文將探討 dropna()drop_duplicates() 方法的應用,並分享一些實戰技巧與最佳實務。

移除缺失值:dropna() 的精妙應用

dropna() 方法如同資料的篩子,可以精準地篩除 DataFrame 中包含缺失值(NaN)的行或列。預設情況下,dropna() 會移除任何包含至少一個 NaN 的整行資料。

import pandas as pd

df = pd.DataFrame([['cold','slow', None, 2.7, 6.6, 3.1],
                   ['warm', 'medium', 4.2, 5.1, 7.9, 9.1],
                   ['hot', 'fast', 9.4, 11.0, None, 6.8],
                   ['cool', None, None, None, 9.1, 8.9],
                   ['cool', 'medium', 6.1, 4.3, 12.2, 3.7],
                   [None, 'slow', None, 2.9, 3.3, 1.7],
                   [None, 'slow', None, 2.9, 3.3, 1.7]],
                  columns=['Temp', 'Speed', 'Measure1', 'Measure2', 'Measure3', 'Measure4'])

df_dropped = df.dropna()
print(df_dropped)

這段程式碼首先構建了一個包含缺失值的 DataFrame,如同一個佈滿陷阱的資料池。接著,dropna() 方法就像一個過濾網,將包含 NaN 的行撈除,並將乾淨的資料儲存到新的 DataFrame df_dropped 中。最後,印出 df_dropped,只會顯示不包含任何 NaN 的行,也就是索引為 1 和 4 的兩行資料,如同從陷阱中篩選出的寶藏。

dropna() 也支援 inplace=True 引數,可以直接修改原始 DataFrame,無需建立新的 DataFrame,如同在資料池中直接清除陷阱。

df.dropna(inplace=True)
print(df)

此處使用 inplace=True 引數,dropna() 方法會直接修改原始的 df DataFrame。執行後,df 中所有包含 NaN 的行都會被刪除,如同直接在資料池中進行清理。

除了刪除行,dropna() 也可以刪除包含 NaN 的列,只需設定 axis=1 引數即可,如同調整過濾網的方向。

df = pd.DataFrame([['cold','slow', None, 2.7, 6.6, 3.1],
                   ['warm', 'medium', 4.2, 5.1, 7.9, 9.1],
                   ['hot', 'fast', 9.4, 11.0, None, 6.8],
                   ['cool', None, None, None, 9.1, 8.9],
                   ['cool', 'medium', 6.1, 4.3, 12.2, 3.7],
                   [None, 'slow', None, 2.9, 3.3, 1.7],
                   [None, 'slow', None, 2.9, 3.3, 1.7]],
                  columns=['Temp', 'Speed', 'Measure1', 'Measure2', 'Measure3', 'Measure4'])

df.dropna(axis=1, inplace=True)
print(df)

設定 axis=1 後,dropna() 會沿著列的方向搜尋 NaN,如同改變了篩選的方向。在此範例中,任何包含 NaN 的列都會被刪除,就像將資料池中垂直方向的陷阱清除。

使用 thresh 引數:更精細的資料保留策略

dropna()thresh 引數可以設定保留行的最低非缺失值數量,如同設定一個資料池的最低水位線。例如,thresh=4 表示只有至少包含 4 個非缺失值的列才會被保留。

df = pd.DataFrame([['cold','slow', None, 2.7, 6.6, 3.1],
                   ['warm', 'medium', 4.2, 5.1, 7.9, 9.1],
                   ['hot', 'fast', 9.4, 11.0, None, 6.8],
                   ['cool', None, None, None, 9.1, 8.9],
                   ['cool', 'medium', 6.1, 4.3, 12.2, 3.7],
                   [None, 'slow', None, 2.9, 3.3, 1.7],
                   [None, 'slow', None, 2.9, 3.3, 1.7]],
                  columns=['Temp', 'Speed', 'Measure1', 'Measure2', 'Measure3', 'Measure4'])

df_thresh = df.dropna(thresh=4)
print(df_thresh)

這裡設定 thresh=4dropna() 方法會保留至少有 4 個非 NaN 值的行。 如同設定了水位線,只有水位線以上的資料會被保留。

  graph LR
    A[載入 DataFrame] --> B{檢查缺失值?}
    B --|有缺失值| C[使用 dropna()]
    C --> D[刪除包含 NaN 的行]
    C --> E[刪除包含 NaN 的列]
    C --> F[刪除非 NaN 值少於 n 的行]
    B --|無缺失值| G[繼續分析]
    D --> G
    E --> G
    F --> G

透過 dropna() 方法的靈活運用,我們可以有效地清除資料中的缺失值,為後續的資料分析奠定堅實的基礎。

持續更新中… (這句話必須移除)

Python 與 SAS 的資料格式轉換之道

身為一個在資料科學領域打滾多年的技術工作者,玄貓經常需要在 Python 和 SAS 之間切換。兩種語言各有千秋,但資料格式的差異有時會造成些許不便。因此,我整理了一些 Python 和 SAS 資料格式轉換的技巧,希望能幫助大家更順暢地運用這兩種工具。

整數格式的顯示控制

Python 和 SAS 預設顯示整數的方式略有不同。以下是如何控制整數顯示格式的技巧:

Python:前導零與正號

在 Python 中,可以使用格式化字串或 f-string 來控制整數的顯示方式。例如,要顯示帶有前導零的整數,可以使用 {:04d} 的格式:

number = 99
formatted_number = f"{number:04d}"  # 或 '{:04d}'.format(number)
print(formatted_number)  # 輸出 0099

04d 表示使用 4 位數字顯示整數,不足 4 位則用 0 填充。d 代表十進位整數。

要顯示帶有前導正號的整數,可以使用 {:+d}{:+04d} 的格式:

number = 99
formatted_number = f"{number:+d}"  # 或 '{:+04d}'.format(number)
print(formatted_number)  # 輸出 +99

+d 表示顯示帶有正號的整數。

SAS:前導零與正號

在 SAS 中,可以使用 z 格式來顯示帶前導零的整數,使用 FORMAT 陳述式定義格式:

data _null_;
  int = 99;
  put int z4.; /* 輸出 0099 */
run;

z4. 格式表示使用 4 位數字顯示整數,不足 4 位則用 0 填充。

要顯示帶前導正號的整數,可以自定義一個 picture 格式:

proc format;
  picture plussign low-high = ' 00' (prefix='+'); /* 定義格式 */
run;

data _null_;
  int = 99;
  put int plussign.; /* 輸出 +99 */
run;

picture 陳述式定義了一個名為 plussign 的格式,prefix='+' 表示在數字前加上正號。

浮點數格式的顯示控制

Python:控制小數位數與百分比格式

Python 中,使用 f-string 可以輕鬆控制浮點數的小數位數:

pi = 3.14159265
formatted_pi = f"{pi:.2f}"  # 或 '{:.2f}'.format(pi)
print(formatted_pi)  # 輸出 3.14

.2f 表示顯示小數點後兩位。

要顯示百分比格式,可以使用 .2%

ratio = 0.0422
formatted_ratio = f"{ratio:.2%}"  # 或 '{:.2%}'.format(ratio)
print(formatted_ratio)  # 輸出 4.22%

.2% 表示將數字乘以 100 後,顯示小數點後兩位,並加上百分號。

SAS:百分比格式

SAS 中,使用 percent 格式顯示百分比:

data _null_;
  pct = 0.0422;
  put pct percent8.2; /* 輸出 4.22% */
run;

percent8.2 格式表示顯示百分比,總長度為 8,小數點後兩位。

日期時間格式處理

Python:日期時間處理

Python 的 datetime 模組提供了強大的日期時間處理功能。以下是如何使用 strftime() 格式化日期時間的示例:

from datetime import datetime

now = datetime.now()
formatted_date = now.strftime("%Y-%m-%d")  # 格式化為 YYYY-MM-DD
formatted_time = now.strftime("%H:%M:%S")  # 格式化為 HH:MM:SS
print(formatted_date)
print(formatted_time)

strftime() 方法可以根據指定的格式字串格式化日期時間。%Y 代表年份,%m 代表月份,%d 代表日期,%H 代表小時,%M 代表分鐘,%S 代表秒。

SAS:日期時間處理

SAS 也提供了豐富的日期時間函式和格式。以下是如何在 SAS 中格式化日期時間的示例:

data _null_;
  now = datetime();
  formatted_date = put(datepart(now), yymmdd10.); /* 格式化為 YYYY-MM-DD */
  formatted_time = put(timepart(now), time8.);   /* 格式化為 HH:MM:SS */
  put formatted_date;
  put formatted_time;
run;

datetime() 函式傳回當前的日期時間。datepart() 函式提取日期部分,timepart() 函式提取時間部分。yymmdd10.time8. 是 SAS 提供的日期和時間格式。

  graph LR
    C[C]
    A[日期時間資料] --> B{Python - datetime}
    A --> C{SAS - 日期時間函式}

圖表説明: 此圖表説明 Python 和 SAS 都能處理日期時間資料,Python 使用 datetime 模組,SAS 使用內建的日期時間函式。

透過這些技巧,我們可以更有效地在 Python 和 SAS 之間轉換資料,並根據需要調整資料格式,以滿足不同的分析需求。

從亂數生成探索 Python 與 SAS 的資料處理差異

在資料分析領域,Python 和 SAS 都是不可或缺的工具。瞭解它們在資料處理上的差異,有助於我們更有效地選擇和使用這些工具。本文將以亂數生成為例,比較 Python 和 SAS 在資料處理方面的特性。

動態型別 vs. 靜態型別

Python 是一種動態型別語言,變數型別在指定時自動確定。SAS 則是一種靜態型別語言,需要事先宣告變數型別。

Python:使用 numpy 和 pandas 生成亂數

import numpy as np
import pandas as pd

np.random.seed(12345)  # 設定亂數種子
random_numbers = pd.Series(np.random.randn(10))  # 生成 10 個標準常態分佈亂數
print(random_numbers)

numpy 函式庫提供高效的數值計算功能,pandas 函式庫提供資料分析工具。np.random.seed() 設定亂數種子,確保結果可重複。pd.Series() 建立一個 pandas Series 物件,用於儲存亂數。

SAS:生成亂數

data _null_;
  call streaminit(12345);  /* 設定亂數種子 */
  do i = 1 to 10;
    x = rand("Normal");  /* 生成標準常態分佈亂數 */
    put x;
  end;
run;

call streaminit() 設定亂數種子。rand("Normal") 函式生成標準常態分佈亂數。

pandas:Python 資料分析的利器

pandas 函式庫是 Python 資料分析的核心工具,提供 SeriesDataFrame 等高效的資料結構。

  graph LR
    A[Python - pandas] --> B(Series)
    A --> C(DataFrame)

圖表説明: pandas 提供 Series (一維) 和 DataFrame (二維) 資料結構,方便資料處理和分析。

Series 類別似於 SAS 中的變數,DataFrame 類別似於 SAS 資料集。pandas 提供豐富的資料操作功能,例如資料清洗、轉換、聚合等,使其成為 Python 資料分析的利器。

透過以上示例,我們可以看出 Python 和 SAS 在資料處理方面各有優勢。Python 的動態型別和 pandas 函式庫使其更加靈活易用,而 SAS 的靜態型別和嚴謹的語法使其更適合大型專案。選擇哪種工具取決於具體的分析需求和個人偏好。

Python 的日期與時間處理:從 datetime 模組到 pandas 資料型別

在資料分析領域,日期和時間資料的處理至關重要。Python 提供了 datetime 模組和 pandas 函式庫,為我們提供了強大的工具來處理這類別資料。datetime 模組定義了日期、時間和日期時間物件,而 pandas 則以其高效的資料結構和函式,簡化了日期時間資料的操作。不同於 SAS 使用數值表示日期時間,Python 以物件的形式儲存,更貼近我們對日期和時間的理解。

Pandas 資料型別:資料科學家的工具箱

pandas 函式庫建立在 NumPy 基礎之上,不僅繼承了 NumPy 的資料型別,也定義了許多專屬的資料型別,例如 datetime64timedelta,專門用於處理日期時間資料。以下表格列出常用的 pandas 資料型別:

Pandas 資料型別Python 資料型別用途
objectstr文字序列
int64int整數
float64float浮點數
boolbool布林值 (True/False)
datetime64-日期和時間值
timedelta-兩個日期時間的差值
category-類別變數

這些資料型別如同資料科學家的工具箱,讓我們能更有效地處理和分析不同型別的資料。object 類別型類別似於 SAS 的字元變數,用於處理字串值。int64float64 分別對應 SAS 的數值型別,用於儲存整數和浮點數。

Pandas 資料結構:Series 與 DataFrame

Pandas 提供了兩種主要的資料結構:Series 和 DataFrame。Series 是一維的標籤化陣列,可以儲存任何資料型別。DataFrame 則是一個二維的表格型資料結構,由多個 Series 組成,分享相同的索引。

資料的序列

Series 就像一列火車,每個車廂都裝載著一個資料值,而車廂的編號就是索引。

import pandas as pd
import numpy as np

# 使用預設索引
s1 = pd.Series(np.random.randn(5))
print(s1)

# 使用自定義索引
s2 = pd.Series(np.random.randn(10), index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'])
print(s2)

這段程式碼首先匯入了 pandasnumpy 兩個函式庫。接著,使用 pd.Series() 建立了兩個 Series:s1 使用預設的數值索引,而 s2 則使用自定義的字母索引。np.random.randn() 用於生成隨機數。

print(s2[0])  # 使用預設數值索引
print(s2['a']) # 使用自定義索引

print(s2[:3])  # 切片,取得前三個元素
print(s2[:'c']) # 切片,取得索引'c'之前的元素

這段程式碼展示瞭如何使用索引和切片來取得 Series 中的元素。可以使用數值索引或自定義索引,切片則可以取得一段範圍內的元素。

DataFrame:資料的表格

DataFrame 就像一個資料表格,由多個 Series 組成。

# 從 CSV 檔案讀取資料
df = pd.read_csv("https://raw.githubusercontent.com/RandyBetancourt/PythonForSASUsers/master/data/uk_accidents.csv")
print(df.shape) # 顯示 DataFrame 的形狀 (列數, 欄數)

這段程式碼使用 pd.read_csv() 從指定的 URL 讀取 CSV 檔案,並建立一個 DataFrame。df.shape 屬性可以顯示 DataFrame 的列數和欄數。

  graph LR
    subgraph DataFrame
        A[欄位 1] --> B(索引)
        C[欄位 2] --> B
        D[欄位 3] --> B
        E[...] --> B
    end

這個圖表展示了 DataFrame 的基本結構:多個欄位分享同一個索引。

print(df.info()) # 顯示 DataFrame 的資訊

df.info() 方法可以顯示 DataFrame 的詳細資訊,包括欄位名稱、資料型別、非空值數量、記憶體使用量等。

深入 DataFrame:資料檢視與探索

RangeIndex:DataFrame 的預設索引

DataFrame 預設使用 RangeIndex 作為行索引,類別似 SAS 的 _N_。我們也可以使用 set_index() 方法設定其他欄位作為索引。

# 建立 DataFrame 時指定索引
df = pd.read_csv('d:\\data\\Customers.csv', index_col=['Last_Name', 'First_Name'])

# 建立後修改索引
df = df.set_index('Customer_ID')

資料型別:info()dtype

info() 方法提供 DataFrame 的資訊概覽,包含資料型別。dtype 屬性則顯示特定欄位的資料型別。

df.info()
print(df['Date'].dtype)


df = pd.read_csv("C:\\Data\\uk_accidents.csv", parse_dates=['Date'])

資料檢視:head()tail()describe()

head()tail() 方法分別顯示 DataFrame 的前幾行和後幾行資料。describe() 方法提供數值型欄位的描述性統計資訊。

print(df.tail(10))
print(df.head(5))
print(df.describe())
  graph LR
    D[D]
A[DataFrame] --> B(head)
A --> C(tail)
A --> D{describe}

資料切片:[[ ]] 運算元

[[ ]] 運算元可以根據欄位標籤選取特定欄位。

print(df[['Sex_of_Driver', 'Time']].head(10))

視覺化探索:直方圖

import matplotlib.pyplot as plt
df.hist(column='Sex_of_Driver', grid=False)
plt.show()

這段程式碼使用 matplotlib.pyplot 函式庫繪製 ‘Sex_of_Driver’ 欄位的直方圖,幫助我們理解資料分佈。

處理 Pandas 缺失值:None 與 NaN

Pandas 使用 NoneNaN 表示缺失值。None 通常用於物件型態,而 NaN 用於數值型態。

import pandas as pd

df1 = pd.DataFrame([['cold', 9],
                   ['warm', 4],
                   [None , 4]],
                   columns=['Strings', 'Integers'])

print(df1)
print(df1.dtypes)

df1.loc[df1.Integers == 9, 'Integers'] = None
print(df1)
print(df1.dtypes)

內容解密

這段程式碼示範了 NoneNaN 的使用。當在整數欄中使用 None 時,Pandas 會自動將該欄的資料型別轉換為浮點數,以容納 NaN

本文探討了 Pandas 的資料型別、資料結構以及處理缺失值的方法,並結合程式碼示例和圖表説明,希望能幫助讀者更好地理解和應用 Pandas 進行資料分析。

import pandas as pd

# 建立範例 DataFrame
data = {'col1': [1, 2, 3, 2, 1], 'col2': [4, 5, 6, 5, 4]}
df = pd.DataFrame(data, index=[0, 1, 2, 3, 4])

# 顯示原始 DataFrame
print("原始 DataFrame:\n", df)

# 使用 drop_duplicates() 刪除重複列
df_no_duplicates = df.drop_duplicates()

# 顯示刪除重複列後的 DataFrame
print("\n刪除重複列後的 DataFrame:\n", df_no_duplicates)


# 建立包含缺失值的 DataFrame
data_with_nan = {'col1': [1, 2, None, 2, 1], 'col2': [4, 5, 6, None, 4]}
df_with_nan = pd.DataFrame(data_with_nan, index=[0, 1, 2, 3, 4])


print("\n包含缺失值的 DataFrame:\n",df_with_nan)

# 使用 dropna() 刪除包含缺失值的列
df_no_nan = df_with_nan.dropna()

print("\n刪除包含缺失值的列後的 DataFrame:\n",df_no_nan)

這段程式碼示範瞭如何使用 Pandas 刪除 DataFrame 中的重複列和處理缺失值。首先,我們建立一個包含重複列的 DataFrame,並使用 drop_duplicates() 方法刪除重複項。接著,我們建立另一個包含缺失值(NaN)的 DataFrame,並使用 dropna() 方法刪除包含 NaN 的列。

  graph LR
    A["建立 DataFrame"] --> B{"包含缺失值?"}
    B -- "Yes" --> C["使用 dropna() 刪除缺失值"]
    B -- "No" --> D{"包含重複資料?"}
    D -- "Yes" --> E["使用 drop_duplicates() 刪除重複資料"]
    D -- "No" --> F["資料清理完成"]
    C --> F
    E --> F

這張流程圖清晰地展現了資料清理的步驟:首先檢查 DataFrame 是否包含缺失值,若有則使用 dropna() 處理;接著檢查是否包含重複資料,若有則使用 drop_duplicates() 處理。最後,完成資料清理。

Pandas 提供了強大的資料清理功能,drop_duplicates()dropna() 是其中兩個非常實用的工具。drop_duplicates() 可以根據所有欄位或指定欄位刪除重複列,而 dropna() 可以刪除包含任何缺失值或指定欄位缺失值的列。 根據實際需求選擇不同的引數和方法,可以更精確地控制資料清理的過程。