--- title: "大数据分析工具" subtitle: 《区域水环境污染数据分析实践》
Data analysis practice of regional water environment pollution author: 苏命、王为东
中国科学院大学资源与环境学院
中国科学院生态环境研究中心 date: today lang: zh format: revealjs: theme: dark slide-number: true chalkboard: buttons: true preview-links: auto lang: zh toc: true toc-depth: 1 toc-title: 大纲 logo: ./_extensions/inst/img/ucaslogo.png css: ./_extensions/inst/css/revealjs.css pointer: key: "p" color: "#32cd32" pointerSize: 18 revealjs-plugins: - pointer filters: - d2 --- ```{r} #| echo: false knitr::opts_chunk$set(echo = TRUE) source("../../coding/_common.R") library(nycflights13) library(tidyverse) ``` # 正则表达式 ## 匹配数字 ### 匹配数字: - \d:匹配任意数字字符。 - \d+:匹配一个或多个数字字符。 - [0-9]: 匹配数字 ### 匹配字母: - \w:匹配任意字母、数字或下划线字符。 - \w+:匹配一个或多个字母、数字或下划线字符。 ## 匹配数字 ### 匹配空白字符: - \s:匹配任意空白字符,包括空格、制表符、换行符等。 - \s+:匹配一个或多个空白字符。 ### 匹配特定字符: - [abc]:匹配字符 a、b 或 c 中的任意一个。 - [a-z]:匹配任意小写字母。 - [A-Z]:匹配任意大写字母。 - [0-9]:匹配任意数字。 ## 匹配数字 ### 匹配重复次数: - {n}:匹配前一个字符恰好 n 次。 - {n,}:匹配前一个字符至少 n 次。 - {n,m}:匹配前一个字符至少 n 次,但不超过 m 次。 ### 匹配边界: - ^:匹配字符串的开头。 - $:匹配字符串的结尾。 ## 匹配数字 ### 匹配特殊字符: - \:转义特殊字符,使其按字面意义匹配。 - .:匹配任意单个字符。 - |:表示“或”关系,匹配两个或多个表达式之一。 #### 匹配次数: - *:匹配前一个字符零次或多次。 - +:匹配前一个字符一次或多次。 - ?:匹配前一个字符零次或一次。 ## 匹配数字 ### 分组和捕获: - ():将一系列模式组合成一个单元,可与特殊字符一起使用。 ### 预定义字符集: - \d:任意数字,相当于 [0-9]。 - \w:任意字母、数字或下划线字符,相当于 [a-zA-Z0-9_]。 - \s:任意空白字符,相当于 [ \t\n\r\f\v]。 ## 实例 ```{r} library(babynames) (x <- c("apple", "apppple", "abc123def")) x[str_detect(x, "[0-9]")] x[str_detect(x, "abc[0-9]+")] x[str_detect(x, "pp")] x[str_detect(x, "p{4}")] x[str_detect(x, "p{4}")] x[str_detect("apple", "ap*")] x[str_detect("apple", "app*")] x[str_detect("apple", "a..le")] ``` ## 练习 找出`babyname`中名字含有ar的行 ```{r} #| echo: false babynames |> filter(str_detect(name, "ar")) ``` ## 练习 找出`babyname`中名字含有ar或者以ry结尾的行。 ```{r} #| echo: false babynames |> filter(str_detect(name, "ar")) ``` # Linux基础知识与开发工具 ## SSH - 安全远程连接 ```bash # 连接到远程服务器 ssh username@remote.server.com # 使用特定端口连接 ssh -p 2222 username@remote.server.com # 执行远程命令 ssh username@server "ls -l /tmp" ``` **案例**: - 远程管理云服务器 - 自动化脚本执行 ## Windows下的SSH工具 - PuTTY ![PuTTY界面](https://www.putty.org/Putty.png) ```bash # 主要功能: 1. 保存会话配置(IP/端口/认证信息) 2. 支持SSH/Telnet/Serial连接 3. 公钥认证(配合Pageant使用) 4. 端口转发(SSH隧道) ``` **案例**: - 连接Linux服务器进行管理 - 建立SSH隧道访问内网资源 ## SCP - 安全文件传输 ```bash # 复制本地文件到远程 scp file.txt username@remote:/path/to/dest # 从远程复制到本地 scp username@remote:/path/file.txt . # 递归复制目录 scp -r dir/ username@remote:/path/ ``` **案例**: - 部署网站文件到生产环境 - 备份远程日志文件 ## Windows下的SCP工具 - WinSCP ![WinSCP界面 w:400](https://winscp-static-746341.c.cdn77.org/data/media/screenshots/commander.png?v=101) ```bash # 主要特性: - 图形化SFTP/SCP客户端 - 与PuTTY集成 - 支持拖拽操作 - 可保存常用连接 - 批处理脚本功能 ``` **案例**: - 可视化管理服务器文件 - 本地与服务器间同步代码 ## Windows替代bash的工具 **1. Git Bash** ```bash # 包含常用Linux命令 ls, grep, ssh, scp, awk等 ``` **2. WSL (Windows Subsystem for Linux)** ```bash # 完整Linux环境 sudo apt install python3 ``` **3. Cygwin** ```bash # POSIX兼容环境 cygwin.com/setup-x86_64.exe ``` ## Windows终端工具推荐 | 工具 | 特点 | 适用场景 | |------|------|----------| | **Windows Terminal** | 多标签/色彩支持 | 日常开发 | | **MobaXterm** | 内置X11/插件 | 远程开发 | | **Tabby** | 跨平台/主题丰富 | 多平台用户 | | **ConEmu** | 高度可定制 | 高级用户 | ## 开发工具跨平台方案 **最佳实践**: 1. 代码编辑器统一使用VS Code(全平台支持) - 配合Remote-SSH插件 2. 数据库工具使用DBeaver/DataGrip 3. 版本控制使用Git GUI(GitKraken/Fork) ```bash # 保持环境一致的建议: - 使用WSL2开发环境 - 配置相同的.ssh/config文件 - 共享相同的IDE配置 ``` ## grep - 文本搜索 ```bash # 基本搜索 grep "error" logfile.txt # 递归搜索目录 grep -r "function" src/ # 显示行号 grep -n "TODO" *.py # 反向匹配 grep -v "success" results.log ``` **案例**: - 在日志中查找错误信息 - 分析代码库中的特定模式 ## sed - 流编辑器 ```bash # 替换文本 sed 's/old/new/g' file.txt # 删除空行 sed '/^$/d' file.txt # 原地编辑文件 sed -i 's/python/python3/g' script.sh ``` **案例**: - 批量重命名文件中的字符串 - 清理数据文件中的不规范格式 ## awk - 文本处理 ```bash # 打印特定列 awk '{print $1,$3}' data.csv # 条件过滤 awk '$3 > 100 {print $0}' sales.txt # 使用分隔符 awk -F',' '{print $2}' users.csv ``` **案例**: - 分析服务器日志统计状态码 - 处理CSV格式数据 ## find & xargs - 文件查找处理 ```bash # 查找并删除 find . -name "*.tmp" -delete # 查找并处理 find /var/log -name "*.log" | xargs ls -lh # 复杂组合 find src/ -type f -name "*.js" | xargs grep -l "deprecated" ``` **案例**: - 清理旧临时文件 - 批量处理项目文件 ## 代码编辑器 - **VS Code**:现代轻量级编辑器 - 丰富的插件生态 - 内置Git支持 - **Vim**:终端高效编辑器 ```bash vim file.txt ``` - **RStudio**:R语言集成环境 - **JupyterLab**:交互式笔记本环境 ## Git版本控制 ```bash # 基本工作流 git clone https://repo.url git add . git commit -m "message" git push # 分支管理 git checkout -b new-feature git merge main ``` **案例**: - 团队协作开发 - 版本回滚与问题追踪 ## MySQL数据库 ```sql -- 基本查询 SELECT * FROM users WHERE age > 18; -- 创建表 CREATE TABLE products ( id INT PRIMARY KEY, name VARCHAR(100) ); -- 数据操作 INSERT INTO products VALUES (1, 'Laptop'); UPDATE products SET price=999 WHERE id=1; ``` **案例**: - Web应用数据存储 - 数据分析与报表生成 # 公开数据获取 ## 案例:全国气象数据 ```{bash} #| eval: false #!/bin/bash logfn="${HOME}/service/log/nationalairquality/nationalairquality.log" workdirfn="${HOME}/service/nationalairquality/" mkdir -p "$(dirname "${logfn}")" touch "${logfn}" echo "$(date '+%Y-%m-%d %H:%M:%S'): 下载大气质量数据" >>"${logfn}" declare -a citynames citynames=(北京市 石家庄市 秦皇岛市) jsonfn="${workdirfn}/nationalairquality_$(date '+%Y%d%m%H').json" jsonfn="nationalairquality_$(date '+%Y%d%m%H').json" # [[ -f "${jsonfn}" ]] && rm "${jsonfn}" echo "[" >"${jsonfn}" for cityname in "${citynames[@]}"; do echo "下载${cityname}空气质量数据..." >>"${logfn}" curl "https://air.cnemc.cn:18007/CityData/GetAQIDataPublishLive?cityName=${cityname}" \ -H 'Accept: */*' \ -H 'Accept-Language: en-US,en;q=0.9' \ -H 'Connection: keep-alive' \ -H 'Referer: https://air.cnemc.cn:18007/' \ -H 'Sec-Fetch-Dest: empty' \ -H 'Sec-Fetch-Mode: cors' \ -H 'Sec-Fetch-Site: same-origin' \ -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36' \ -H 'X-Requested-With: XMLHttpRequest' \ -H 'sec-ch-ua: "Google Chrome";v="119", "Chromium";v="119", "Not?A_Brand";v="24"' \ -H 'sec-ch-ua-mobile: ?0' \ -H 'sec-ch-ua-platform: "macOS"' \ --compressed --silent | jq | sed -e '1d' -e '$d' -e 's/^\( *}\)$/\1,/' >>"${jsonfn}" done sed -i '' '$s/},/}/' "${jsonfn}" echo "]" >>"${jsonfn}" echo "大气质量数据下载完成!" >>"${logfn}" echo "开始上传数据库..." >>"${logfn}" /home/ming/bin/getnationalairquality.R "${jsonfn}" echo "上传数据库完毕!" >>"${logfn}" ``` ## R代码 ```{r} #| eval: false #| echo: true #!/usr/bin/Rscript jsonfn <- commandArgs(TRUE)[1] # jsonfn <- "~/nationalairquality_2023191219.json" jsondf <- jsonlite::fromJSON(jsonfn, flatten = TRUE) # metadf <- tibble::as_tibble(jsondf) |> # dplyr::select(site = StationCode, name = PositionName, Area, lon = Longitude, lat = Latitude) |> # dplyr::mutate(lon = as.numeric(lon), lat = as.numeric(lat)) # DBI::dbWriteTable(conn, "metadf", metadf, overwrite = TRUE, row.names = FALSE) airqualitydf <- tibble::as_tibble(jsondf) |> dplyr::select( datetime = TimePoint, site = StationCode, `CO_mg/m3` = CO, `CO_24h_mg/m3` = CO_24h, `NO2_μg/m3` = NO2, `NO2_24h_μg/m3` = NO2_24h, `O3_μg/m3` = O3, `O3_24h_μg/m3` = O3_24h, `O3_8h_μg/m3` = O3_8h, `O3_8h_24h_μg/m3` = O3_8h_24h, `PM10_μg/m3` = PM10, `PM10_24h_μg/m3` = PM10_24h, `PM2.5_μg/m3` = PM2_5, `PM2.5_24h_μg/m3` = PM2_5_24h, `SO2_μg/m3` = SO2, `SO2_24h_μg/m3` = SO2_24h, `NO_μg/m3` = NO, `NO_24h_μg/m3` = NO_24h, `NOx_μg/m3` = NOx, `NOx_24h_μg/m3` = NOx_24h, AQI, COLevel, NO2Level, O3Level, O3_8hLevel, PM10Level, PM2_5Level, SO2Level, PrimaryPollutant, Quality, Unheathful ) |> dplyr::mutate(dplyr::across( `CO_mg/m3`:AQI, ~ round(readr::parse_number(.x), 4) )) |> dplyr::mutate(datetime = lubridate::as_datetime(datetime)) conn <- cctdb::get_dbconn("nationalairquality", writepermission = TRUE) DBI::dbWriteTable( conn, "airqualitydf", airqualitydf, append = TRUE, row.names = FALSE ) DBI::dbDisconnect(conn) ``` ## 欢迎讨论!{.center} `r rmdify::slideend(wechat = FALSE, type = "public", tel = FALSE, thislink = "https://drc.drwater.net/course/public/RWEP/PUB/SD/")`