今日學習主題:數據整理與清洗(二)
核心目標
掌握dplyr和tidyr包的高級數據操作,能夠靈活處理複雜數據。
一、dplyr 高級操作
1. 條件篩選與變形
# 示例數據
df <- tibble(
id = 1:10,
value = c(5, 15, -3, 8, 20, -7, 12, 9, -1, 6),
category = rep(c("A", "B"), each = 5)
)
# 條件創建新變量
df <- df %>%
mutate(
value_category = case_when(
value < 0 ~ "Negative",
value >= 0 & value < 10 ~ "Low",
value >= 10 ~ "High",
TRUE ~ "Other"
),
scaled_value = ifelse(value > 0, log(value + 1), value) # 對正數取對數
)
2. 跨列操作
# 創建寬數據
df_wide <- tibble(
id = 1:5,
sales_2020 = c(100, 150, 80, 200, 90),
sales_2021 = c(120, 160, 85, 220, 95),
sales_2022 = c(130, 170, 90, 240, 100)
)
# 計算每年的增長率(跨列操作)
df_wide <- df_wide %>%
mutate(
growth_2021 = (sales_2021 - sales_2020) / sales_2020 * 100,
growth_2022 = (sales_2022 - sales_2021) / sales_2021 * 100
)
# 使用across()進行批量操作
df_wide <- df_wide %>%
mutate(across(starts_with("sales"), ~ round(. / max(.) * 100, 2), .names = "scaled_{.col}"))
二、tidyr 高級數據變形
1. 複雜數據的寬長轉換
# 創建複雜數據
complex_df <- tibble(
student = rep(c("Alice", "Bob"), each = 2),
subject = rep(c("Math", "English"), times = 2),
score_midterm = c(85, 78, 92, 88),
score_final = c(88, 80, 95, 85),
attendance = c(95, 90, 98, 92)
)
# 轉換為長數據
long_df <- complex_df %>%
pivot_longer(
cols = c(score_midterm, score_final, attendance),
names_to = "metric_type",
values_to = "value"
)
# 分離指標類型
long_df <- long_df %>%
separate(metric_type, into = c("metric", "period"), sep = "_", fill = "right")
2. 嵌套數據框
# 創建嵌套數據
nested_data <- df %>%
group_by(category) %>%
nest() %>%
mutate(
summary = map(data, ~ tibble(
mean = mean(.x$value),
sd = sd(.x$value),
n = nrow(.x)
))
)
# 展開嵌套數據
unnested_data <- nested_data %>%
unnest_wider(summary)
三、數據處理管道的高級應用
1. 條件管道操作
# 根據條件決定是否執行某步驟
process_data <- function(data, remove_negatives = TRUE) {
data %>%
{if(remove_negatives) filter(., value >= 0) else .} %>%
mutate(
category = factor(category),
value_group = cut(value, breaks = 3, labels = c("Low", "Medium", "High"))
)
}
2. 多數據集操作
# 創建多個相關數據集
sales_data <- tibble(
id = 1:5,
product = c("A", "B", "C", "A", "B"),
sales = c(100, 200, 150, 120, 180)
)
price_data <- tibble(
product = c("A", "B", "C"),
price = c(10, 20, 15)
)
# 合併並計算總價值
combined <- sales_data %>%
left_join(price_data, by = "product") %>%
mutate(total_value = sales * price) %>%
group_by(product) %>%
summarise(total_sales = sum(sales), total_revenue = sum(total_value))
四、實際案例:電商數據清洗
# 模擬電商數據
set.seed(123)
ecommerce_data <- tibble(
order_id = 1:100,
customer_id = sample(1:20, 100, replace = TRUE),
product = sample(c("Laptop", "Phone", "Tablet", "Headphones"), 100, replace = TRUE),
price = round(runif(100, 50, 1000), 2),
quantity = sample(1:5, 100, replace = TRUE),
order_date = sample(seq(as.Date('2023-01-01'), as.Date('2023-12-31'), by="day"), 100)
)
# 數據清洗與分析
cleaned_data <- ecommerce_data %>%
# 處理異常值
mutate(
price = ifelse(price > 2000, NA, price), # 價格超過2000設為NA
quantity = ifelse(quantity > 10, 1, quantity) # 數量異常調整為1
) %>%
# 計算衍生變量
mutate(
total_value = price * quantity,
month = format(order_date, "%Y-%m"),
weekday = weekdays(order_date)
) %>%
# 分組分析
group_by(product, month) %>%
summarise(
total_quantity = sum(quantity, na.rm = TRUE),
total_revenue = sum(total_value, na.rm = TRUE),
avg_price = mean(price, na.rm = TRUE),
.groups = "drop"
) %>%
# 計算月度增長率
group_by(product) %>%
arrange(month) %>%
mutate(
revenue_growth = (total_revenue - lag(total_revenue)) / lag(total_revenue) * 100
)
五、今日實踐任務
- 任務1:使用
case_when()創建更復雜的條件變量
- 對數值變量進行多級分類
- 根據多個條件組合創建新變量
- 任務2:處理寬表數據
- 將包含多個年份/月份指標的寬錶轉換為長表
- 從長錶轉換回寬表,但使用不同的結構
- 任務3:實現數據清洗管道
- 創建一個函數,接受數據和參數,執行完整的數據清洗流程
- 包括異常值處理、缺失值插補、變量轉換等步驟
- 任務4:分析嵌套數據
- 對分組後的數據應用不同的彙總函數
- 使用
map()系列函數對每個子集進行建模或分析
六、學習建議
- 理解數據思維:數據整理不僅是技術操作,更是理解數據結構和分析需求的過程
- 代碼可讀性:寫管道時適當換行和註釋,保持代碼清晰
- 錯誤處理:在關鍵步驟添加數據驗證,確保處理過程正確
- 性能考慮:對於大數據,考慮使用
data.table或dtplyr
七、擴展學習(可選)
- 學習
purrr包的高級迭代函數 - 瞭解
furrr包進行並行處理 - 探索
recipes包進行更復雜的數據預處理
今天的內容將幫助你建立更強大的數據處理能力。明天我們將開始數據可視化(ggplot2)的深入學習,將整理好的數據轉化為有意義的圖表。
堅持就是勝利!你已經完成了17天的學習,離掌握R語言又近了一步!