[{"content":"","date":"5 March 2025","externalUrl":null,"permalink":"/en/tags/ielts/","section":"Tags","summary":"","title":"Ielts","type":"tags"},{"content":"","date":"2025-03-05","externalUrl":null,"permalink":"/","section":"Nand Fun","summary":"","title":"Nand Fun","type":"page"},{"content":"","date":"2025-03-05","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":" 所有文章，什么题材都有\u0026hellip; ","date":"2025-03-05","externalUrl":null,"permalink":"/posts/","section":"博客","summary":" 所有文章，什么题材都有… ","title":"博客","type":"posts"},{"content":"","date":"2025-03-05","externalUrl":null,"permalink":"/tags/%E9%9B%85%E6%80%9D/","section":"Tags","summary":"","title":"雅思","type":"tags"},{"content":" 我第一次雅思考试成绩为 7 —— 听8 读8 写6 说5.5 本文总结了我备考雅思的种种经验和做题技巧\n有关考试基本的信息（如考试流程、试题构成等）请自行寻找其他材料\n个人经验有限，自行判断该指导哪些部分适用于你 各科备考经验 # 听力 # 题目有规律，各个部分固定是学术/生活、独白/多人 需要不少词汇量，要能听辨、理解、拼写，总会碰到不知道的，防不胜防 提前看好能填几个词语，通过题干预判数字/名词/动词/复数 等词性，尤其仔细听复数等词性，尤其仔细听复数 定位词非常重要，题目如果太难就靠定位词来圈定答案位置，判断听到哪个题目 每次空隙都尽可能去划后面题目定位词，之前不会错过了就不要管了 Part1 的邮编、电话、地址、日期、金额等固定考点多练习 推荐拿到考题先去看 Part3 的题目，标出关键定位词，等要开始了赶紧去看 Part1 阅读 # 本质上雅思阅读就是找题目对应原文 词汇量要求比较高，推荐去把四六级雅思核心高频词都背下来能认出来 别背生僻词语，只背词频高的，剑雅和机经里收集的只是特定素材里的词，生僻词在考试时候能猜出个大概，且基本肯定不是考点 注意阅读速度，练习时要定时，一般时间分配 10+15+25，不要在特定题目纠结太久，都是一分的题 做题先浏览标题、题干、每段开头结尾，再根据题目看原文，不要看完文章才做题目 学习平行阅读法，即根据题型是否按照文章顺序出现，交叉做题，一次阅读同时做完多个题型，避免反复低效阅读 掌握略读和细读能力，用题干定位词快速找到目标范围，然后细读找答案 写作 # 时间分配为小作文15，大作文40+5分钟构思 作文的题型和结构都是套路，结构可根据情况粗略调整，记好连接词和套路句子，锻炼思路即可 小作文考察描述能力，结构：Paraphrase + Overview + Detail1 + Detail2，记好每种题型常用词，练习怎么找重点 大作文考察说服能力，结构：Introduction + Body1 + Body2 + Conclusion，学习观点 + 议论 + 举例 的论述方法 口语 # 口语是绝大多数非英语母语者最头疼的，要锻炼用英语思考和能说出来的能力 推荐练习时大声说出来，把自己的回答录下来，锻炼把握时间能力 不要用拗口高深大词，贴切小词更好，关键是自然流畅 没必要提前“背诵”，不像自然口语反而效果不好，有思路最重要 练习一些过渡词汇（如 you know, I mean, well\u0026hellip;），填补思考时间，增加口语感 可提前准备 Part1 的题目，问的都是有关于你生活的简单问题，简单回答就好 Part2 话题太多了，建议把题型打包，只准备一些特定记忆深刻的人物、物品、事件，一个素材多用 Part3 能多说就多说，头脑风暴，考的就是英语能力 重要资料 # 建议以下资料迅速浏览一遍，快速选择适合自己的资料然后制定学习计划\nIELTS Ready Premium：雅思官方的，报考了能免费用，有非常细节的课程和练习，用来熟悉题型、练口语（一问一答）和写作（有各分数范文）特别好 IELTS Liz：综合网站，包含了大量雅思练习和技巧，同名 Youtube 频道 IELTS-up：同样综合网站，尤其是总结了很多写作的词句，推荐写作的时候有意识使用 Sun老师教雅思：包含各种雅思相关知识，最重要的是听力和阅读的手把手带练，可以清晰看到做题老手的策略和划关键词的选择 慎小嶷系列书籍：《十天突破雅思写作》和《十天突破雅思口语》推荐买纸质版仔细研读 雅思机考哥：非常好的机考模拟软件，用它就不用买剑雅纸质书，模拟体验和真实无异，非常推荐用来把剑雅刷穿 墨墨背单词：尽早背高频词，不要背生僻词，用英英与例句方式代入语境背，可以自己找网上高频词自定义词表 AI 雅思作文批改：也可以用其他 AI，低成本高效检查错词错句错思路，立等可取 最后但同样重要 # 错题数对应分数：雅思官网以及各种教培网站都有，关注这个干嘛，你要控分吗！？能考多少考多少啊 预约考试：一定要去把雅思官网的公告通知全看了，尽早订下考试时间，给自己 deadline，避免拖延 机考/纸笔：凡是能在普通键盘上有足够打字能力的都推荐机考，可以自行用软件模拟对比，优点很多，尤其是写作可以随意排版且不用担心字迹（我在考场上反复调整段落与语句顺序，甚至可以把零零散散的语句都写上再组合） 补习班：如果你有足够的自驱力与信息搜索能力，完全可以不报，更何况一般补习的价格都够你好几次真实考试了 考试当天：建议尽量约早上的场，同时约下午尽可能早的口语考试。英语临时抱佛脚没有什么用处，不如趁着早上的状态一鼓作气，免得压力过大 机经：没有刷过，感觉剑雅就够多练了。不过口语考虑到换题季可以看一下最近的机经，比较有时效性 长期学习 # 如果你追求长期培养英语能力，或是想知道语言学习的本质和方法，罗肖尼Shawney的讲解（可理解输入假说）就是答案：\n如何永远学会一个单词 这个视频将会颠覆你对英语学习的认知——听说篇 这个视频将会颠覆你对英语学习的认知——总述·阅读篇 总的来说，流利外语来自于海量听读可理解的材料，寻找难度适中（i+1，即略高于你目前水平）、有趣、足量系列材料，在大量输入下宛如学母语习得语感后才能自然开口输出\n","date":"2025-03-05","externalUrl":null,"permalink":"/posts/ielts-preparation-guide/","section":"博客","summary":" 我第一次雅思考试成绩为 7 —— 听8 读8 写6 说5.5 本文总结了我备考雅思的种种经验和做题技巧\n","title":"雅思备考指南","type":"posts"},{"content":"","date":"17 October 2024","externalUrl":null,"permalink":"/en/tags/configuration/","section":"Tags","summary":"","title":"Configuration","type":"tags"},{"content":"","date":"2024-10-17","externalUrl":null,"permalink":"/tags/macos/","section":"Tags","summary":"","title":"MacOS","type":"tags"},{"content":"","date":"2024-10-17","externalUrl":null,"permalink":"/tags/%E9%85%8D%E7%BD%AE/","section":"Tags","summary":"","title":"配置","type":"tags"},{"content":" 合理的配置和高效的功能软件，打造顺畅、高效工作流 内容将按照配置的顺序进行解释，部分内容可根据个人需求进行选择性配置\n建议先略读全文，不要急于配置，有些应用的深度配置依赖其他应用，万万不可一口气照做到底！ 先决条件 # VPN (可选) # 大多计算机相关的应用中国大陆都无法较难访问，若中国大陆用户想舒适配置请务必完成此步骤。\nCommand Line Tools (CLT) for Xcode # 对 macOS 用户，系统自带 bash、git 和 curl，在命令行输入 xcode-select --install 安装 CLT for Xcode。\nHomebrew # macOs 上最重要的应用，请自行学习 Homebrew 详细的各种使用方法\nHomebrew 是 macOS 使用最广泛且最好用的包管理器，基本上各类“小”应用（即除了Chrome等大而强健的）都推荐优先使用包管理下载、管理。\n中国大陆用户推荐按照清华大学开源软件镜像站安装配置，最好直接换源。若大陆用户有 VPN ，也可直接按照 Homebrew 官网使用终端命令直接安装。\nGitHub（推荐） # 推荐注册并配置 GitHub ssh 协议连接服务。\n基本应用 # Zsh # 首先使用 brew 安装 zsh，设置为默认 shell brew install zsh chsh -s $(which zsh) 我使用 Oh My Zsh 作为管理使用 zsh 的框架和包管理器，按照官网命令行安装即可 Oh My Zsh 有非常丰富的插件系统，推荐安装或启用的插件可参照我的 .zshrc，请务必清楚每一行配置文件的含义再添加。 可使用诸如 Starship 这样的工具来美化 prompt，可参考我的配置文件。 Node.js # 推荐使用 fnm 对多 Node.js 环境进行版本管理，使用 brew 安装，参照其官网进行配置使用即可。\nJava # 推荐使用 jenv 对多 Java 环境进行版本管理，使用 brew 安装，参照其官网进行配置使用即可。\nConda # 推荐安装 Miniconda，更轻量，按照官方文档安装即可。\nRust # 按照官网使用命令行安装即可。\nGolang # 按照官网使用命令行安装即可。\n生产力工具 # Karabiner-Elements # 强大且稳定的键盘自定义工具\n推荐官网下载，功能强大，对键鼠都有高度自定义的空间。\niTerm2 # iTerm2 是一款终端模拟器，是 Terminal 的替代品，也是 iTerm 的继任者。不仅外观更佳且功能更强，推荐配置热键与主题。\n推荐使用 brew 安装，也可在官网下载安装。\nNeoVim # 高度可扩展的基于 Vim 的文本编辑器，我一般用于在命令行进行轻量的文件快速编辑\n建议使用 brew 安装，NewVim 的深度配置较为复杂（博大精深），不过有大量已进行配置的“发行版”，我个人使用 LunarVim ，进行了一定的配置。\nLunarVim 涉及大量依赖，请仔细遵循其官方文档安装 JetBrains # 推荐使用 JetBrains Toolbox App 进行 JetBrains 系列软件的安装、管理。\nVsCode # 较为轻量全能的编辑器\n推荐官网安装。\nRaycast # 免费的，更强大的 Alfred 的上位替代\n推荐使用 brew 安装，也可在官网下载安装。\n插件生态强大，功能极多，务必在插件市场上好好逛上一逛！ Tuxera # 用于微软的 NTFS 格式硬盘在 Mac 上使用，个人使用该付费软件，有其他替代品。\nPeek # Mac App Store 可下载，macOS 在文件上按空格可快速预览，Peek 加强了该功能，支持更多格式的文件。\niStat Menus # 终极系统监视器\n新版本界面更美观了 Mac 上最好用的检测器，可自定义状态栏，丰富详细的监控数据。\nBetter365 # 官网在此，这个公司有非常多的实用 mac 应用，本人使用的如下：\niShot：截图、长截图、贴图、标注、取色、录屏工具 FastZip：优秀免费的压缩解压工具 自动切换输入法：能帮你自动切换输入法（中英文） iBar：隐藏菜单栏图标 Better And Better：Mac 必备的鼠标、触控板、键盘手势工具 draw.io # draw.io 是免费的在线图表软件，可用于制作流程图、过程图、组织结构图、UML 图、ER 图和网络图。\nBob # 个人使用该翻译 \u0026amp; OCR 软件，功能强大，在 Mac Appstore 下载，是付费软件。\nYabai # macOS 的平铺式窗口管理器\n主要是 macOS 本身的窗口切换和管理过于缓慢繁琐，我很喜欢它多 space 的设计，但是切换太麻烦了。\nyabai 有完整的 Wiki，也可参考我的 yabai 配置文件。\nSketchyBar # A highly customizable macOS status bar replacement\nGitHub 链接在此，可配合 Yabai 使用，功能丰富，可参考我的配置文件。\n","date":"2024-10-17","externalUrl":null,"permalink":"/posts/ultimate-macos-setup/","section":"博客","summary":" 合理的配置和高效的功能软件，打造顺畅、高效工作流 内容将按照配置的顺序进行解释，部分内容可根据个人需求进行选择性配置\n","title":"终极 macOS 配置方案","type":"posts"},{"content":"我总是尽力挤出时间工作和学习新技能。不过我的大多数小项目最终都没产生什么影响。然而，它们确实让我学到了不少，帮我在现实世界得到了更多机会。\n项目经历 # 图标 链接 描述 Shuohua macOS 轻量语音输入：实时转写、按需润色、自动上屏 Owl 舒适灵活的分体式无线键盘 Vision Guard 智能监控和安全系统 Subway Route Finder 重庆地铁线路快捷查询系统 Budget Buddy 财务管理器，导入微信/支付宝账单，分析生成报告 Moon Phase Tracker 查询任何所选日期的月相 Word Wise 通过基于关键词的主题来组织文本文件的文件管理器 工作经验 # 公司 网址 职位 任期 地点 第四范式 软件开发（实习） 2026.04 - 2026.08 中国广东深圳 Digiwin 后端开发（实习） 2024.07 - 2024.10 中国江苏南京 iFlytek 软件开发（实习） 2024.03 - 2024.05 中国重庆 教育经历 # 学校 网址 学位 时期 香港中文大学（深圳） 计算机科学研究生 2025 - 2027 西南大学 计算机科学本科 2021 - 2025 温州中学 高中 2018 - 2021 温州外国语学校 初中 2015 - 2018 ","date":"2024-09-25","externalUrl":null,"permalink":"/about/","section":"Nand Fun","summary":"我总是尽力挤出时间工作和学习新技能。不过我的大多数小项目最终都没产生什么影响。然而，它们确实让我学到了不少，帮我在现实世界得到了更多机会。\n","title":"关于","type":"page"},{"content":"","date":"15 August 2024","externalUrl":null,"permalink":"/en/tags/keyboard/","section":"Tags","summary":"","title":"Keyboard","type":"tags"},{"content":"","date":"15 August 2024","externalUrl":null,"permalink":"/en/series/owl-split-keyboard/","section":"Series","summary":"","title":"Owl Split Keyboard","type":"series"},{"content":"","date":"2024-08-15","externalUrl":null,"permalink":"/series/owl-%E5%88%86%E4%BD%93%E9%94%AE%E7%9B%98/","section":"Series","summary":"","title":"Owl 分体键盘","type":"series"},{"content":" \u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 如果您在安装过程中遇到任何困难，请充分发挥DIY能力，使用各种可行的部件 Switch Socket # 请根据所选的 PCB 选择相应的轴座。\n普通版本可用标准轴和佳达隆矮轴，Choc 版本使用标准轴和凯华矮轴\nRGB # 单面需要 23 个轴灯和 6 个底灯，因此串联所以请全部安装或不安装。为了便于拿取和手动焊接，只使用 SK6812MINI-E。已在 PCB 上标记了安装 GND 引脚的位置。安装时，只需注意轴灯 LED 面朝下，底灯 LED 面朝上。\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 它们的方向相反 二极管 # 每个轴对应一个二极管，可自由选择贴片二极管或穿孔二极管，可以自由选择安装在 PCB 的两面（在背面安装可能会与外壳发生冲突）。\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 无论如何，请确保二极管的方向正确 开关与电池 # 重置和启动开关以及电源插座非常容易焊接。值得注意的是，直插式开关背面凸出的针脚应该打磨和修剪，以免影响外壳的安装。\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 请注意电池正负极的顺序 芯片和 Oled # 由于 PCB 是双面，可以将芯片安装在任何一侧，无论是直接焊接还是连接到插座上。应该安装芯片引脚的位置在每一侧都有标记，请小心不要焊接错误。\n\u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 如果你想使用 3D 打印外壳，请务必遵循以下步骤！ 建议使用矮插槽在键盘正面安装芯片，安装插槽时请注意对准印刷线路板上标记的列，安装芯片时请确保芯片背面（无元件的平面一面）朝上。最后，安装 OLED 屏幕时请确保安装牢固。\n外壳 # 3D 打印外壳 # 首先，将五个热熔螺母安装到 3D 打印外壳中，然后将完成的 PCB 放置其中，拧紧五个螺柱，最后安装背板和正面 OLED 亚克力保护板。\n透明外壳 # 这种外壳没有太多需要注意的地方，只需使用 M2 螺柱和螺丝进行连接。\n轴体 # 硬件最后一步是安装轴体和键帽，最简单的一步，请尽情发挥您的创造力进行搭配。\n固件 # 此键盘使用 ZMK 作为固件，请 fork 我的 zmk-config 仓库和 zmk 官方文档，推荐使用 GitHub Action 和keymap-editor 进行网页可视化固件构建。\n刷固件非常简单，只需快速按两次启动按钮进入引导模式，键盘控制器就会像 U 盘一样出现在电脑里，将固件拖入即可更新。\n","date":"2024-08-15","externalUrl":null,"permalink":"/posts/owl-keyboard-assembly/","section":"博客","summary":" \u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 如果您在安装过程中遇到任何困难，请充分发挥DIY能力，使用各种可行的部件 Switch Socket # 请根据所选的 PCB 选择相应的轴座。\n","title":"Owl 键盘：组装","type":"posts"},{"content":"","date":"2024-08-15","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"},{"content":"","date":"2024-08-15","externalUrl":null,"permalink":"/tags/zmk/","section":"Tags","summary":"","title":"ZMK","type":"tags"},{"content":"","date":"2024-08-15","externalUrl":null,"permalink":"/tags/%E9%94%AE%E7%9B%98/","section":"Tags","summary":"","title":"键盘","type":"tags"},{"content":" \u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 请仔细阅读指南，也可参考其他分割键盘构造指南作为参考 PCB # 物品 数量 备注 PCB 2 如果使用 3D 打印外壳，则用 1.6mm 厚 ProMicro 2 nice!nano 二极管 46 SOD-123 或 DO-35 重置开关 2 3*6*5 电池开关 2 MSK-1102-1.5H 电池插座 2 PH2.0 2P 电池 2 3.7V 锂电池（最大 40*50*70） PCB 轴座 46 兼容标准轴和佳达隆矮轴，如使用 choc 版本 PCB 则兼容凯华矮轴 轴体 46 按照你选择的轴座选择对应轴体 键帽 46 1u 键帽 Previous Next 可选 # RGB 和 Oled # 物品 数量 备注 OLED 2 0.91 英寸 SK6812MINI-E 58 因为它们是串连的，所以需要全部安装 Previous Next 外壳 # 标准外壳 # 物品 数量 备注 M2 螺柱 12mm 4 用于垫高 OLED 盖板 M2 螺丝 24 至少 3mm 脚垫 任意 防滑 透明外壳 # 物品 数量 备注 定位板 2 1.5mm-4mm 底板 2 至少 1.5mm OLED 盖板 2 至少 1mm M2 螺柱 7mm 10 放于 PCB 和底板之间 3D 打印外壳 # 物品 数量 备注 M2 螺柱 7+4mm 10 放于 PCB 和底板之间 热熔螺母 M2*3*3.5 10 用烙铁熔入外壳 3D 打印外壳 2 随意选择打印材料 OLED 盖板 2 2mm 底板 2 2mm ","date":"2024-08-14","externalUrl":null,"permalink":"/posts/owl-keyboard-materials/","section":"博客","summary":" \u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 请仔细阅读指南，也可参考其他分割键盘构造指南作为参考 PCB # 物品 数量 备注 PCB 2 如果使用 3D 打印外壳，则用 1.6mm 厚 ProMicro 2 nice!nano 二极管 46 SOD-123 或 DO-35 重置开关 2 3*6*5 电池开关 2 MSK-1102-1.5H 电池插座 2 PH2.0 2P 电池 2 3.7V 锂电池（最大 40*50*70） PCB 轴座 46 兼容标准轴和佳达隆矮轴，如使用 choc 版本 PCB 则兼容凯华矮轴 轴体 46 按照你选择的轴座选择对应轴体 键帽 46 1u 键帽 Previous Next 可选 # RGB 和 Oled # 物品 数量 备注 OLED 2 0.91 英寸 SK6812MINI-E 58 因为它们是串连的，所以需要全部安装 Previous Next 外壳 # 标准外壳 # 物品 数量 备注 M2 螺柱 12mm 4 用于垫高 OLED 盖板 M2 螺丝 24 至少 3mm 脚垫 任意 防滑 ","title":"Owl 键盘：材料","type":"posts"},{"content":" Owl (Orthogonal Wireless Layout) \u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 人体工学无线蓝牙分体键盘 设计灵感来源于 Lily58、Corne、Sofle 和 Torn 键盘。\n特点 # Owl 使用 Pro Micro 小型控制板，易于维护更换。并支持多种板子，包括 nice!nano 和 nrfmicro（尚未尝试，但理论上可行）。 低延迟无线连接，使用 ZMK 构建。 支持 RGB 灯光效果。 两个多功能 OLED 屏幕，可显示电量、连接状态、输入状态。 分体式键盘设计符合人体工程学。 两种 PCB 设计，兼容 Cherry MX 轴、Kailh choc 矮轴和 Gateron 矮轴。 双面 PCB 设计，翻面互用。 DIY # 请确保您具备以下能力来制作键盘:\n焊接电路元件 PCB 制作 3D 打印 使用 GitHub Action 来构建固件 仔细阅读文档 \u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 继续阅读 Owl 分体键盘 系列来制作键盘 版权 # Owl 键盘使用 知识共享 署名-非商业性使用 4.0 国际 许可协议。\n此 PCB 设计可以自由地进行复制、修改和制造，仅限于个人使用。如果您想商业使用此设计，请联系 hza2002@foxmail.com 以请求许可。\n","date":"2024-08-13","externalUrl":null,"permalink":"/posts/owl-keyboard-overview/","section":"博客","summary":" Owl (Orthogonal Wireless Layout) \u003c?xml version=\"1.0\" encoding=\"UTF-8\" ?\u003e \u003c!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 1.1//EN\" \"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\"\u003e 人体工学无线蓝牙分体键盘 设计灵感来源于 Lily58、Corne、Sofle 和 Torn 键盘。\n","title":"Owl 键盘：概述","type":"posts"},{"content":"","date":"10 January 2023","externalUrl":null,"permalink":"/en/tags/convolution/","section":"Tags","summary":"","title":"Convolution","type":"tags"},{"content":"","date":"10 January 2023","externalUrl":null,"permalink":"/en/tags/image-filtering/","section":"Tags","summary":"","title":"Image Filtering","type":"tags"},{"content":"","date":"10 January 2023","externalUrl":null,"permalink":"/en/tags/image-processing/","section":"Tags","summary":"","title":"Image Processing","type":"tags"},{"content":"","date":"10 January 2023","externalUrl":null,"permalink":"/en/tags/linear-algebra/","section":"Tags","summary":"","title":"Linear Algebra","type":"tags"},{"content":"","date":"2023-01-10","externalUrl":null,"permalink":"/tags/%E5%8D%B7%E7%A7%AF/","section":"Tags","summary":"","title":"卷积","type":"tags"},{"content":"","date":"2023-01-10","externalUrl":null,"permalink":"/tags/%E5%9B%BE%E5%83%8F%E5%A4%84%E7%90%86/","section":"Tags","summary":"","title":"图像处理","type":"tags"},{"content":" 图像是由一个一个像素点组成的，处理图像的本质就是处理这些像素点。像素之间的关联性是重要的信息，不能完全把像素点割裂开来，这一点也正是众多图像算法的出发点。卷积（Convolution）是数学中的一种常用的运算。在图像处理中，它通过将图像和卷积核进行运算来改变图像的细节。图像的卷积或滤波操作在各种场合应用很普遍，如各种滤镜、卷积神经网络等。本文将将通过图像滤波，探讨在图像处理领域的卷积中应用的线性代数知识。 图像处理介绍 # 图像处理是指对图像进行分析、加工和处理，使其满足视觉、心理或其他要求的技术。图像处理是信号处理在图像领域上的一个应用。目前大多数的图像均是以数码形式存储，因而图像处理很多情况下指数字图像处理。此外，基于光学理论的处理方法依然占有重要的地位。\n图像在计算机中由大量看似连续的像素构成，在数学上图像的每个像素可以对应为线性代数里矩阵的每个元素，因此使用矩阵表示图像。图像的种类不同，矩阵的维数会有变化：灰度格式的图像可用一个元素值介于0～255之间的二维矩阵来表示，元素值的大小对应着像素点的亮度（0对应黑色，255对应白色）；彩色图像（RGB图像）可用三维矩阵表示，红（R）、绿（G）、蓝（B）三个分量分别用一个矩阵表示，3个矩阵组合起来构成三维矩阵。可以说，图像就等于矩阵，所以线性代数中有关矩阵理论的成果可以应用于图像处理上。\n图像的简单几何变化 # 将图像信息看作矩阵进行处理，我们能够利用线性代数中有关矩阵理论的知识对图像进行简单的几何变化。下面介绍几种常见的图像几何变换原理，其中\\(x\u0026rsquo;\\)，\\(y\u0026rsquo;\\)为平移后图像像素坐标，\\(x_0\\)，\\(y_0\\)为各方向偏移量，\\(x\\)，\\(y\\)为原图像中像素坐标。\n平移（Translation） # $$ \\begin{bmatrix} x\u0026rsquo; \\cr y\u0026rsquo; \\cr 1 \\end{bmatrix} = \\begin{bmatrix} 1\u0026amp;0\u0026amp;x_0\\cr 0\u0026amp;1\u0026amp;y_0\\cr 0\u0026amp;0\u0026amp;1 \\end{bmatrix} \\begin{bmatrix} x \\cr y \\cr 1 \\end{bmatrix} $$\n旋转（Rotation） # $$ \\begin{bmatrix} x\u0026rsquo; \\cr y\u0026rsquo; \\cr 1 \\end{bmatrix} = \\begin{bmatrix} cos\\theta\u0026amp;-sin\\theta\u0026amp;0 \\cr sin\\theta\u0026amp;cos\\theta\u0026amp;0 \\cr 0\u0026amp;0\u0026amp;1 \\end{bmatrix} \\begin{bmatrix} x \\cr y \\cr 1 \\end{bmatrix} $$\n旋转后可能无法完美的映射至每一个新的像素点，故需要后期对旋转后的图像进行修复，但通常由于缺失的点并不多，可采用取前一像素的RGB值来实现。\n缩放（Scale） # $$ \\begin{bmatrix} x\u0026rsquo; \\cr y\u0026rsquo; \\cr 1 \\end{bmatrix} = \\begin{bmatrix} c\u0026amp;0\u0026amp;0 \\cr 0\u0026amp;d\u0026amp;0 \\cr 0\u0026amp;0\u0026amp;1 \\end{bmatrix} \\begin{bmatrix} x \\cr y \\cr 1 \\end{bmatrix} $$\n显然，放大后会出现没有图像信息的空格，故需要对这些空格进行补充。我们可以使用双线性插值对输出图像进行插值补充。\n双线性插值原理 分别在左上、右上、左下、右下四个方向寻找最近且有有效RGB信息的像素点，计算其到需要插值的像素点的距离 \\(d_{ul}\\), \\(d_{ur}\\), \\(d_{dl}\\), \\(d_{dr}\\), 根据其反比关系给予对应点权值，即有\n$$p_{ul}:p_{ur}:p_{dl}:p_{dr}= {1\\over d_{ul}}:{1\\over d_{ur}}:{1\\over d_{dl}}:{1\\over d_{dr}}$$\n将权值映射至\\([0,1]\\), 然后对需插值点的每个通道进行加权赋值：\n$$\\begin{bmatrix} R\u0026rsquo; \\cr G\u0026rsquo; \\cr B' \\end{bmatrix}=p_{ul}\\begin{bmatrix} R_{ul} \\cr G_{ul} \\cr B_{ul} \\end{bmatrix}+p_{ur}\\begin{bmatrix} R_{ur} \\cr G_{ur} \\cr B_{ur} \\end{bmatrix}+p_{dl}\\begin{bmatrix} R_{dl} \\cr G_{dl} \\cr B_{dl} \\end{bmatrix}+p_{dr}\\begin{bmatrix} R_{dr} \\cr G_{dr} \\cr B_{dr} \\end{bmatrix}$$\n对所有间隙进行以上操作即可完成整张图像的插值\n错切（Shear） # shear on axis-x（沿x轴错切）\\(\\begin{bmatrix} x\u0026rsquo; \\cr y\u0026rsquo; \\cr 1 \\end{bmatrix}=\\begin{bmatrix} 1\u0026amp;d_x\u0026amp;0 \\cr 0\u0026amp;1\u0026amp;0 \\cr 0\u0026amp;0\u0026amp;1 \\end{bmatrix}\\begin{bmatrix} x \\cr y \\cr 1 \\end{bmatrix}\\)\nshear on axis-y（沿y轴错切）\\(\\begin{bmatrix} x\u0026rsquo; \\cr y\u0026rsquo; \\cr 1 \\end{bmatrix}=\\begin{bmatrix} 1\u0026amp;0\u0026amp;0 \\cr d_y\u0026amp;1\u0026amp;0 \\cr 0\u0026amp;0\u0026amp;1 \\end{bmatrix}\\begin{bmatrix} x \\cr y \\cr 1 \\end{bmatrix}\\)\n镜像（Mirror） # $$ \\begin{bmatrix} x\u0026rsquo; \\cr y\u0026rsquo; \\cr 1 \\end{bmatrix}= \\begin{bmatrix} s_x\u0026amp;0\u0026amp;0 \\cr 0\u0026amp;s_y\u0026amp;1 \\cr 0\u0026amp;0\u0026amp;1 \\end{bmatrix} \\begin{bmatrix} x \\cr y \\cr 1 \\end{bmatrix} $$\n卷积 # 原理 # 卷积是两个变量在某范围内相乘后求和的结果。卷积一词最开始出现在信号与线性系统中，信号与线性系统中讨论的就是信号经过一个线性系统以后发生的变化。由于现实情况中常常是一个信号前一时刻的输出影响着这一时刻的输出，所在一般利用系统的单位响应与系统的输入求卷积，以求得系统的输出信号（当然要求这个系统是线性时不变的）。\n如果卷积的变量是序列\\(x(n)\\)和\\(h(n)\\)，则卷积的结果：\n$$ y(n)=\\sum_{i=-\\infty}^{\\infty} x(i) h(n-i)=x(n) * h(n) $$\n图像处理中的卷积 # 在图像处理中，卷积可以用来对图像进行滤波、特征提取和其他处理。卷积运算在数学上可以用线性代数的方法来描述，其实也是仿射变换的一种：对输入向量进行线性变换。\n卷积满足线性函数的定义，若\\(f(𝑥)\\)满足以下两个条件, 则说\\(f(𝑥)\\)是一个线性函数:\n$$ \\begin{aligned} 𝑓(𝑥1+𝑥2) \u0026amp;= 𝑓(𝑥1)+𝑓(𝑥2) \\cr 𝑓(𝑎𝑥) \u0026amp;= 𝑎𝑓(𝑥) \\end{aligned} $$\n由于数字图像是一个二维的离散信号，对数字图像做卷积操作其实就是利用卷积核在图像上滑动，将图像点上的像素值与对应的卷积核上的数值相乘，然后将所有相乘后的值相加作为卷积核中间像素对应的图像上的像素值。最终滑动完所有像素，这样新图像中的每个像素值就是原图像的一部分像素值和卷积核的权值的乘积之和。\n给定一个输入图像\\(f(x,y)\\)和一个卷积核\\(g(x,y)\\)，卷积运算的结果是一个新的图像\\(h(x,y)\\)，其中\n$$ h(x,y) = ∑∑ f(u,v) * g(x-u, y-v) $$\n卷积核\\(g(x,y)\\)是一个小的矩阵，用来对输入图像进行卷积运算，而输出图像\\(h(x,y)\\)则是一个新的图像，它是由\\(g(x,y)\\)与\\(f(x,y)\\)的卷积而得到的。设\\(H\\)是卷积运算的结果，是一个新的矩阵，\\(F\\)是输入图像的矩阵表示，\\(G\\)是卷积核的矩阵表示，那么卷积运算可以表示为：\\(H = G * F\\)\n图像滤波 # 图像滤波的目的是在尽量保留图像特征的条件下，过滤掉图像中的噪声，是图像预处理中不可缺少的操作，其滤波效果直接影响到后续图像识别、分析等算法的效果。\n对图像的滤波处理的本质就是对图像应用一个卷积核。通过不同的卷积核，可以实现不同的图像处理效果，例如增强边缘、去除噪声、提取特征等。\n以下是关于卷积核的一些总结：\n卷积核往往是行数和列数均为奇数的矩阵，这样中心较好定位。 卷积核元素的总和体现出输出的亮度，若元素总和为1，卷积后的图像与原图像亮度基本一致；若元素总和为0，则卷积后的图像基本上是黑色，其中较亮的部分往往就是提取出图像的某种特征。 高通滤波器（High Pass Filter, HPF）表示仅允许图像中高频部分（即图片中变化较剧烈的部分）通过，往往用于对图像进行锐化处理、增强图像中物体边缘等。 低通滤波器（Low Pass Filter, LPF）表示仅允许图像中低频部分（即图片中变化较平缓的部分）通过，往往用于对图像进行模糊/平滑处理、消除噪点等。 下面给出一些图像滤波方法并附上效果示意图供参考。\n图像的均值滤波 # \\(x\u0026rsquo;\\),\\(cy\u0026rsquo;\\)为平移后图像像素坐标，\\(x_0\\),\\(y_0\\)为各方向偏移量，\\(x\\),\\(y\\)为原图像像素坐标\n均值滤波器的主要应用是去除图像中的不相干细节，即那些与滤波掩模尺寸相比更小的像素区域。通过一个掩膜（以\\(3\\times 3\\)为例）对每个像素及其周围一周的像素取平均后重新赋值来实现。\n$$ Pixel\u0026rsquo;={1\\over9}\\times \\begin{bmatrix} 1\u0026amp;1\u0026amp;1 \\end{bmatrix} \\begin{bmatrix} 1\\cdot P_{ul} \u0026amp; 1\\cdot P_{up} \u0026amp; 1\\cdot P_{ur} \\cr 1\\cdot P_{l} \u0026amp; 1\\cdot P \u0026amp; 1\\cdot P_{r} \\cr 1\\cdot P_{dl} \u0026amp; 1\\cdot P_{down} \u0026amp; 1\\cdot P_{dr} \\end{bmatrix} \\begin{bmatrix} 1 \\cr 1 \\cr 1 \\end{bmatrix} $$\n图像均值滤波示例 拉普拉斯图像增强 # 原理：Laplace算子可以近似计算出图像的二阶导数，具有旋转不变性，也就是可以检测出各个方向的边缘。\n拉普拉斯算子：\n$$ \\nabla^2f={\\partial^2f\\over\\partial x^2}+{\\partial^2f\\over\\partial y^2} $$\n其中有：\n$$ \\begin{aligned} {\\partial^2f\\over\\partial x^2}=f(x+1,y)+f(x-1,y)-2f(x,y) \\cr {\\partial^2f\\over\\partial y^2}=f(x,y+1)+f(x,y-1)-2f(x,y) \\end{aligned} $$\n将对角线方向加入讨论之后\n$$ \\begin{aligned} {\\nabla^2f}=[f(x-1,y-1)+f(x,y-1)+f(x-1,y)+f(x+1,y)+\\cr f(x-1,y+1)+f(x,y+1)+f(x+1, y+1)]-8f(x,y) \\end{aligned} $$\n由于边缘处存在像素信息值的陡然变化，即一阶导数有一个极大值，于是可以通过这一特点，对其进一步求二阶导等于0，上式是对二阶导离散化后的结果。通过拉普拉斯算子，可以取出图像的信息值(RGB某一通道值)突变的部分，这一部分便是图像的边缘部分，最后与原图像叠加，从而获得边缘增强（锐化）的图像。（其中\\(Pixel\u0026rsquo;\\)为变换后图像像素坐标）\n滤波： $$ Pixel\u0026rsquo;={1\\over9} \\times \\begin{bmatrix} 1\u0026amp;1\u0026amp;1 \\end{bmatrix} \\begin{bmatrix} 1\\cdot P_{ul} \u0026amp; 1\\cdot P_{up} \u0026amp; 1\\cdot P_{ur} \\cr 1\\cdot P_{l} \u0026amp; -8\\cdot P \u0026amp; 1\\cdot P_{r} \\cr 1\\cdot P_{dl} \u0026amp; 1\\cdot P_{down} \u0026amp; 1\\cdot P_{dr} \\end{bmatrix} \\begin{bmatrix} 1 \\cr 1 \\cr 1 \\end{bmatrix} $$\n叠加： $$ Pixel\u0026rsquo;\u0026rsquo;=Pixel - Pixel' $$\n拉普拉斯图像增强示例 ","date":"2023-01-10","externalUrl":null,"permalink":"/posts/linear-algebra-in-imaging/","section":"博客","summary":" 图像是由一个一个像素点组成的，处理图像的本质就是处理这些像素点。像素之间的关联性是重要的信息，不能完全把像素点割裂开来，这一点也正是众多图像算法的出发点。卷积（Convolution）是数学中的一种常用的运算。在图像处理中，它通过将图像和卷积核进行运算来改变图像的细节。图像的卷积或滤波操作在各种场合应用很普遍，如各种滤镜、卷积神经网络等。本文将将通过图像滤波，探讨在图像处理领域的卷积中应用的线性代数知识。 图像处理介绍 # 图像处理是指对图像进行分析、加工和处理，使其满足视觉、心理或其他要求的技术。图像处理是信号处理在图像领域上的一个应用。目前大多数的图像均是以数码形式存储，因而图像处理很多情况下指数字图像处理。此外，基于光学理论的处理方法依然占有重要的地位。\n","title":"图像处理中的线性代数","type":"posts"},{"content":"","date":"2023-01-10","externalUrl":null,"permalink":"/tags/%E5%9B%BE%E5%83%8F%E6%BB%A4%E6%B3%A2/","section":"Tags","summary":"","title":"图像滤波","type":"tags"},{"content":"","date":"2023-01-10","externalUrl":null,"permalink":"/tags/%E7%BA%BF%E6%80%A7%E4%BB%A3%E6%95%B0/","section":"Tags","summary":"","title":"线性代数","type":"tags"},{"content":"","date":"8 January 2023","externalUrl":null,"permalink":"/en/tags/circular-permutation/","section":"Tags","summary":"","title":"Circular Permutation","type":"tags"},{"content":"","date":"8 January 2023","externalUrl":null,"permalink":"/en/tags/probability/","section":"Tags","summary":"","title":"Probability","type":"tags"},{"content":" 百囚徒挑战是一个反直觉的问题，它描述了一个看似不可能的事件：100 名囚犯有概率地做同一件事，只有全部囚犯都做成了，他们才能生存下去。这个问题实际上有一种合理的实现方法，将其概率提高近 30 个数量级。 问题描述 # 百囚问题是概率论和组合数学中的一个数学问题。在这个问题中，100 名编号囚犯必须在 100 个抽屉中找到自己的号码才能生存。规则规定，每个囚犯只能打开 50 个抽屉，不能与其他囚犯交流。丹麦计算机科学家 Peter Bro Miltersen 于 2003 年首次提出了这个问题。作为这个问题的升级版本，将有 \\(2N\\) 名囚犯。他们对应的 \\(2N\\) 个号码卡被洗牌并放置在 \\(2N\\) 个抽屉中。每个囚犯最多只能打开一半的抽屉，找到对应自己号码的号码卡。所有囚犯将分别进入房间，任何一个囚犯的失败都会导致整个挑战的失败，囚犯获胜的最大概率是多少?\n问题分析 # 随机打开抽屉 # 假设所有囚犯均随机地在 \\(100\\) 个抽屉里打开 \\(50\\) 个抽屉。\n设随机变量 \\(X_i\\) 如下。\n$$ X_i=\\begin{cases} 1\\quad \\text{There is number i note in 50 drawers.}\\cr 0\\quad \\text{There is no number i note in 50 drawers.} \\end{cases} $$\n带有自己编号的纸条所在的抽屉满足均匀分布，因此抽到有自己编号的纸条的抽屉的概率 \\(P(X_i=1)=\\frac{50}{100}=\\frac{1}{2}\\) 。又由于所有囚犯开抽屉都是独立的，因此所有囚犯均拿到带有自己编号的纸条的概率\n$$ \\begin{aligned} P(X_1=1,X_2=1,\\cdots,X_{100}=1)=\u0026amp;P(X_1=1) \\cdots P(X_{100}=1)\\cr =\u0026amp;0.5^{100}\\cr \\approx \u0026amp;7.89 \\times 10^{-31} \\end{aligned} $$\n这个概率显然太低了，甚至低于在 \\(1\\times 10^{30}\\) 个囚犯中选中一个“幸运儿”获得特赦！\n按照方法打开抽屉 # 引理1：将抽屉的编号视为数值，将纸条的编号视为指针，则房间内存在且仅存在若干的环。\n证明 因为抽屉的编号和纸条的编号都是从 1 到 100 的，所以每一个抽屉都有且只有唯一一个纸条的编号对应，每个纸条又都分别装在一个抽屉里，因此不存在空指的纸条或没纸条的抽屉，即房间里存在的都是环。 引理2：若无次数限制，每个人都能以该方法找到带有自己编号的纸条，即有自己编号的纸条一定在自己走的环中。\n证明 由引理1可知，因为最初开的是带有自己编号的抽屉，所以在此环中，一定有带有自己编号的纸条指向带有自己编号的抽屉，即若无步数限制，一定能找到带有自己编号的纸条。 此时我们可以将问题转化为，假设囚犯均根据上述方法行动，求所有囚犯获得特赦的概率 \\(P\\) 。由引理2，我们可以进一步将问题抽象为：在 \\(100\\) 个随机编号 \\(1-100\\) 的结点所形成的若干个环中，求所有环的长度不超过 \\(50\\) 的环概率 \\(P\\) 。\n一般情况 # 通过对百囚问题的理论分析，我们进一步分析了这一问题的一般解决方案，即 \\(2N\\) 囚犯的最佳策略。\n当有 \\(2N\\) 名囚犯，通过 按照方法打开抽屉 分析，我们可以给出以下最优策略。\\(2N\\) 名囚犯随机标记 \\(2N\\) 个抽屉。当每个囚犯进入房间时，他们选择与自己标签相同数字的抽屉，取出便条，并继续打开与便条上数字相同的抽屉，如此循环。\n如果抽屉 \\(k\\) 中的数字是 \\(s\\)，那么这种策略可以表示为 \\(f(s)=k\\)，其中 \\(f\\) 是一个从抽屉编号到数字编号的映射，即从当前抽屉到下一个抽屉。这个映射具有以下特性:\n$$ \\exists i, 1 \\leq i \\leq 2N, \\underbrace{f \\circ \\cdots \\circ f}_{i \\text{ times}}(s) = s $$\n目前，囚犯成功的条件是:\n$$ \\forall s, 1 \\leq s \\leq 2N, \\exists i, 1 \\leq i \\leq N, \\underbrace{f \\circ \\cdots \\circ f}_{i \\text{ times}}(s) = s $$\n对于任何数字，通过应用该函数 \\(i\\) 次，它都可以映射到自身。\n因此，这种策略的样本空间是所有可能的映射集合。有 \\(2N!\\) 种可能的排列。如果至少需要 \\(m\\) 次映射，某个数字才能映射回自身，那么我们有以下情况的数量。\n$$ C_{2N}^m \\cdot (m-1)! \\cdot (2N-m)! = \\frac{(2N)!}{m} $$\nThe probability that a number can return to itself after at least m mapping is\n$$ P(m) = \\frac{\\frac{(2N)!}{m}}{(2N)!} = \\frac{1}{m} $$\n当 \\(m \\ge N+1\\) 时，各种情况是互斥的，因此囚徒成功的概率如下：\n$$ P = 1 - \\sum_{m=N+1}^{2N} \\frac{1}{m} $$\n应用与实验 # 百囚问题验证 # 根据 按照方法打开抽屉 中的理论分析，我们可以进一步推断。如果存在长度大于 \\(50\\) 的环，那么这样的环的数量必须是 \\(1\\) ，因此我们考虑长度大于 \\(50\\) 的环的存在概率 \\(P\u0026rsquo;\\) 。显然，这两个事件是互补的，所以 \\(P = 1 - P\u0026rsquo;\\) 。\n首先，考虑一个长度为 \\(100\\) 的循环。如果循环在任何一点被打断，则有 \\(A_{100}^{100}=100!\\) 种方式。然后，如果循环被重新连接，循环上的任何一点都可以被视为起点，即循环旋转被视为同一种情况，所以实际的情况数为 \\(\\frac{100!}{100}\\) 。在 \\(100\\) 个抽屉中随机放置 \\(100\\) 个纸条的总情况数为 \\(A_{100}^{100}={100!}\\) 。因此，长度为 \\(100\\) 的循环出现的概率为：\n$$ P_{100}=\\frac{\\frac{100!}{100}}{100} = \\frac{1}{100} $$\n同样地，考虑一个长度为 \\(k (k \u0026gt; 50)\\) 的循环周期。首先，选择 \\(k\\) 个元素作为循环周期的元素，共有 \\(C_{100}^k\\) 种方式；将它们在循环周期上随机排列，共有 \\(\\frac{k!}{k}\\) 种方式；剩余的 \\(100-k\\) 个元素随机分配，共有 \\((100-k)!\\) 种情况；因此，具有长度为 \\(k\\) 的循环周期的情况数为：\n$$ C_{100}^k \\cdot \\frac{k!}{k} \\cdot (100-k)! = \\frac{100!}{k} $$\n因此，长度为 \\(k\\) 的循环的概率是：\n$$ P_k=\\frac{\\frac{100!}{k}}{100!}=\\frac{1}{k} $$\n由于长度为 \\(k (k \u0026gt; 50)\\) 的循环的存在情况彼此独立，\\(P\u0026rsquo;=\\sum_{i=51}^{100} P_i\\)，并通过计算机程序可以得到 \\(P\u0026rsquo; \\approx 0.688\\)。\n以下是 C 语言代码:\n#include \u0026lt;stdio.h\u0026gt; int main() { double sum = 0; for (int i = 51; i \u0026lt;= 100; i++) { sum = sum + 1.0 / i; } printf(\u0026#34;sum=%lf\\n\u0026#34;, sum); return 0; } 结果如下：\ngcc sum_p.c - o sum_p \u0026amp;\u0026amp;./ sum_p sum = 0.0688172 因此，\\(P=1-P\u0026rsquo;\\approx 0.312\\)，这种方法显然比 随机打开抽屉 的概率为\\(7.89 \\times 10^{-31}\\)更可行。\n验证一般情况 # 使用 MATLAB 仿真验证计算结果。当囚犯人数为 \\(2-50\\) 时，对于每种情况，模拟 \\(10000\\) 次并统计释放囚犯的频率，以获得图中的曲线。\n红色曲线根据 一般情况 中的 \\(P=1-\\sum_{m=N+1}^{2N} \\frac{1}{m}\\) 绘制，蓝色曲线通过模拟得到。模拟得到的结果与理论计算值大致相同，验证了理论计算的正确性。\n以下是 MATLAB 代码：\nloop_times = 10000; theo_prob = []; simu_prob = []; for i = 2:2:50 total = 0; for k = i / 2 + 1:1:i total = total + 1 / k; end theo_prob = [theo_prob, 1 - total]; not_release = 0; for j = 1:1:loop_times draw = rand([i, 1]); [temp, draw] = sort(draw); flag = 0; for n = 1:1:i index = n; for m = 1:1:i index = draw(index); if (index == n) \u0026amp;\u0026amp; (m \u0026lt;= i / 2) break elseif (index == n) \u0026amp;\u0026amp; (m \u0026gt;= i / 2 + 1) flag = 1; n = i + 1; break end end end not_release = not_release + flag; end simu_prob = [simu_prob, 1 - not_release / loop_times]; i; end x = 2:2:50; plot(x, theo_prob, \u0026#39;ro-\u0026#39;) hold on; plot(x, simu_prob, \u0026#39;b+-\u0026#39;) legend({\u0026#39;Theoretical value\u0026#39;, \u0026#39;Analog value\u0026#39;}, \u0026#39;Location\u0026#39;, \u0026#39;southwest\u0026#39;) title(\u0026#34;Probability of prisoners\u0026#39; success\u0026#34;) xlabel(\u0026#34;Number of prisoners\u0026#34;) ylabel(\u0026#34;Probability value\u0026#34;) 缩放公式 \\(P=1-\\sum_{m=N+1}^{2N}\\frac{1}{m}\\) 会得到以下结果。\n$$ P \u0026gt; 1-\\int_{N+1}^{2N} \\frac{1}{dx} = 1-\\ln 2 \\approx 0.307 $$\n这意味着这个概率的下限为\\(1-\\ln2\\)。\n结论 # 根据上述计算结果，我们知道即使囚犯数量更多，所有囚犯仍然有近三分之一的成功概率 —— 这与我们最初的直觉相悖，起初我们的直觉告诉我们，让100个囚犯找到自己的编号几乎是不可能的。这种策略的关键在于将所有人的结果集合在一起，尽可能共同成功或失败。最终只有两种可能：存在长度大于50的循环，或不存在。因此只有两种结果：完全胜利或完全失败 —— 没有只有少数人失败的结果。\n不要根据直觉思考问题，而要根据严格的计算得到问题的答案。 ","date":"2023-01-08","externalUrl":null,"permalink":"/posts/100-prisoners-problem/","section":"博客","summary":" 百囚徒挑战是一个反直觉的问题，它描述了一个看似不可能的事件：100 名囚犯有概率地做同一件事，只有全部囚犯都做成了，他们才能生存下去。这个问题实际上有一种合理的实现方法，将其概率提高近 30 个数量级。 问题描述 # 百囚问题是概率论和组合数学中的一个数学问题。在这个问题中，100 名编号囚犯必须在 100 个抽屉中找到自己的号码才能生存。规则规定，每个囚犯只能打开 50 个抽屉，不能与其他囚犯交流。丹麦计算机科学家 Peter Bro Miltersen 于 2003 年首次提出了这个问题。作为这个问题的升级版本，将有 \\(2N\\) 名囚犯。他们对应的 \\(2N\\) 个号码卡被洗牌并放置在 \\(2N\\) 个抽屉中。每个囚犯最多只能打开一半的抽屉，找到对应自己号码的号码卡。所有囚犯将分别进入房间，任何一个囚犯的失败都会导致整个挑战的失败，囚犯获胜的最大概率是多少?\n","title":"百囚问题","type":"posts"},{"content":"","date":"2023-01-08","externalUrl":null,"permalink":"/tags/%E6%A6%82%E7%8E%87/","section":"Tags","summary":"","title":"概率","type":"tags"},{"content":"","date":"2023-01-08","externalUrl":null,"permalink":"/tags/%E7%8E%AF%E6%8E%92%E5%88%97/","section":"Tags","summary":"","title":"环排列","type":"tags"},{"content":"","date":"22 June 2022","externalUrl":null,"permalink":"/en/tags/data-analysis/","section":"Tags","summary":"","title":"Data Analysis","type":"tags"},{"content":"","date":"22 June 2022","externalUrl":null,"permalink":"/en/series/data-analysis-in-r/","section":"Series","summary":"","title":"Data Analysis in R","type":"series"},{"content":"","date":"22 June 2022","externalUrl":null,"permalink":"/en/tags/r-language/","section":"Tags","summary":"","title":"R Language","type":"tags"},{"content":"","date":"2022-06-22","externalUrl":null,"permalink":"/tags/r%E8%AF%AD%E8%A8%80/","section":"Tags","summary":"","title":"R语言","type":"tags"},{"content":"","date":"2022-06-22","externalUrl":null,"permalink":"/series/r%E8%AF%AD%E8%A8%80%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/","section":"Series","summary":"","title":"R语言数据分析","type":"series"},{"content":"数据来源：乳腺癌预测数据集\n简介 # 全球范围内，乳腺癌是女性最常见的癌症类型，在死亡率方面排名第二。当发现异常肿块（来自自我检查或X光）或看到钙质小点（在X光片上）时，就会进行乳腺癌的诊断。在发现可疑肿块后，医生将进行诊断以确定是否为癌症，如果是，是否已扩散到身体的其他部位。\n此乳腺癌数据集是从威斯康星大学麦迪逊分校的威廉·H·沃尔伯格博士处获得的。\n导入 # 第一步是将原始数据导入程序代码。\ndata \u0026lt;- read.csv(\u0026#34;Breast_cancer_data.csv\u0026#34;) 原始数据包含标题，使用R语言中导入CSV文件的内置函数(read.csv)，只需一行简单的代码即可高效地将文件导入我们的程序进行后续处理。\n使用head函数，我们可以简要查看数据的一部分。\nhead(data) # mean_radius mean_texture mean_perimeter mean_area mean_smoothness diagnosis # 1 17.99 10.38 122.80 1001.0 0.11840 0 # 2 20.57 17.77 132.90 1326.0 0.08474 0 # 3 19.69 21.25 130.00 1203.0 0.10960 0 # 4 11.42 20.38 77.58 386.1 0.14250 0 # 5 20.29 14.34 135.10 1297.0 0.10030 0 # 6 12.45 15.70 82.57 477.1 0.12780 0 显然，数据集中每条数据包含5个与乳腺癌相关的数据，最后列使用0和1来表示是否确诊。\n清洗数据 # 一般来说，为了分析数据，我们需要在一定程度上清洗数据，分离和合并一些单元格数据，丢弃一些不需要的数据，并放大重要数据，以便使数据对我们建模和分析更加紧凑。\n我们期望使用数据来构建模型。对这个数据集，每条信息都有其利用价值，因此为了确保数据量充足，我们不需要对其进行过多处理。\n检查缺失数据 # 我们需要判断数据集中是否存在缺失数据，以避免在构建模型时出现未预见的错误。\nsum(is.na(data)) 幸运的是，我们的数据集中没有缺失数据，每一份数据都是完整且充满利用价值的。\n查看冗余数据 # 首先，我们需要确保数据集中的数据没有重复，以防止对后续建模造成干扰。\nduplicated_count \u0026lt;- sum(duplicated(data)) 输出 0，无重复数据。\n分析数据 # 我们的目标是建立一个合理的预测模型，通过某些可量化数据实现乳腺癌诊断的准确预测。\n分析变量分布 # 为了对参数分布有一个基本了解，我们将分别映射每个变量的分布。在这种情况下，直方图和密度分布图的组合是最直观和有效的。由于geom_density()的纵向轴是密度估计，为了能够在同一坐标系中绘制直方图和密度估计，有必要将直方图的纵向轴改为密度估计。\nrel_area \u0026lt;- ggplot(data, aes(x = mean_area, y = ..density..)) + geom_histogram(fill = \u0026#34;blue\u0026#34;, color = \u0026#34;black\u0026#34;, size = 0.2, alpha = 0.2, bins = 30) + geom_density() rel_radius \u0026lt;- ggplot(data, aes(x = mean_radius, y = ..density..)) + geom_histogram(fill = \u0026#34;blue\u0026#34;, color = \u0026#34;black\u0026#34;, size = 0.2, alpha = 0.2, bins = 30) + geom_density() rel_texture \u0026lt;- ggplot(data, aes(x = mean_texture, y = ..density..)) + geom_histogram(fill = \u0026#34;blue\u0026#34;, color = \u0026#34;black\u0026#34;, size = 0.2, alpha = 0.2, bins = 30) + geom_density() rel_smooth \u0026lt;- ggplot(data, aes(x = mean_smoothness, y = ..density..)) + geom_histogram(fill = \u0026#34;blue\u0026#34;, color = \u0026#34;black\u0026#34;, size = 0.2, alpha = 0.2, bins = 30) + geom_density() rel_perimeter \u0026lt;- ggplot(data, aes(x = mean_perimeter, y = ..density..)) + geom_histogram(fill = \u0026#34;blue\u0026#34;, color = \u0026#34;black\u0026#34;, size = 0.2, alpha = 0.2, bins = 30) + geom_density() 最后，我们使用gridExtra库中的grid.arrange函数将图表排列在一起。\ngrid.arrange(rel_area, rel_radius, rel_texture, rel_smooth, rel_perimeter, nrow = 3, ncol = 2 ) 我们注意到所有数据的分布有两个特性：\n所有数据在某个区间内连续分布。 每个数据在某个值附近大量分布，距离越远，分布越少。 单变量诊断结果分析 # 分析每个变量与诊断结果之间的相关性，使用绘制箱形图的方法\n平均半径 # ggplot(data, aes(x = factor(diagnosis), y = mean_radius)) + geom_boxplot(outlier.colour = \u0026#34;blue\u0026#34;, outlier.shape = 5, outlier.size = 4) + labs(title = \u0026#34;Plot of mean_radius\u0026#34;, x = \u0026#34;diagnosis\u0026#34;) 乳腺癌患者的平均肿瘤半径主要在10至15之间，而未诊断的患者主要在15至20之间。\n平均纹理 # ggplot(data, aes(x = factor(diagnosis), y = mean_texture)) + geom_boxplot(outlier.colour = \u0026#34;blue\u0026#34;, outlier.shape = 5, outlier.size = 4) + labs(title = \u0026#34;Plot of mean_texture\u0026#34;, x = \u0026#34;diagnosis\u0026#34;) 可以发现在患者的肿瘤中，平均纹理值介于15到20之间，而尚未被诊断的肿瘤则介于20到25之间。\n平均周长 # ggplot(data, aes(x = factor(diagnosis), y = mean_perimeter)) + geom_boxplot(outlier.colour = \u0026#34;blue\u0026#34;, outlier.shape = 5, outlier.size = 4) + labs(title = \u0026#34;Plot of mean_perimeter\u0026#34;, x = \u0026#34;diagnosis\u0026#34;) 如图所示，确诊患者肿瘤的平均周长在70至90之间，而未诊断的患者在100至130之间。\n平均面积 # ggplot(data, aes(x = factor(diagnosis), y = mean_area)) + geom_boxplot(outlier.colour = \u0026#34;blue\u0026#34;, outlier.shape = 5, outlier.size = 4) + labs(title = \u0026#34;Plot of mean_area\u0026#34;, x = \u0026#34;diagnosis\u0026#34;) 可以发现在确诊患者的平均肿瘤面积约为500，而主要未诊断的肿瘤在750到1250之间。\n平均平滑度 # ggplot(data, aes(x = factor(diagnosis), y = mean_smoothness)) + geom_boxplot(outlier.colour = \u0026#34;blue\u0026#34;, outlier.shape = 5, outlier.size = 4) + labs(title = \u0026#34;Plot of mean_smoothness\u0026#34;, x = \u0026#34;diagnosis\u0026#34;) 我们注意到，在阳性或阴性确认结果的病人中存在肿瘤平滑度的交集，但总体而言，确认病人的数值将会更低。\n相关性分析 # 根据建模的一般过程，我们需要对每个变量进行相关性分析。如果变量之间的相关性显著，它将影响模型的预测效果。\ncor_analysis \u0026lt;- cor(data[c(1:5)]) corrplot(cor_analysis, method = \u0026#34;number\u0026#34;) 通过相关性分析，我们发现这三个变量之间的关系非常显著。它们是半径、周长和面积。这三个值显然高度相关，因此我们需要对它们进行筛选。\n变量与诊断结果的相关性 # 在定性分析模型最终精度之前，我们想先通过图像看看变量和诊断结果之间的关系。有一些直观的印象。\n我们有总共五个变量：\nmean_radius mean_texture mean_perimeter mean_area mean_smoothness 它们与诊断结果之间的相关性被结合，总共有10种情况需要讨论和分析。\n下图中红色圆点表示诊断结果为未诊断\n变量之间的弱相关性 # radius \u0026amp; texture, radius \u0026amp; smoothness, texture \u0026amp; perimeter, texture \u0026amp; area, texture \u0026amp; smoothness, perimeter \u0026amp; smoothness, area \u0026amp; smoothness\n我们可以通过图表中的散点分布直观地理解两个变量之间的关系。\n变量之间强相关性 # radius \u0026amp; perimeter, radius \u0026amp; area, perimeter \u0026amp; area\n# radius \u0026amp; perimeter rpPlot \u0026lt;- ggplot(data, aes( x = mean_radius, y = mean_perimeter, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) # radius \u0026amp; area raPlot \u0026lt;- ggplot(data, aes( x = mean_radius, y = mean_area, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) # perimeter \u0026amp; area paPlot \u0026lt;- ggplot(data, aes( x = mean_perimeter, y = mean_area, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) grid.arrange(rpPlot, raPlot, paPlot, nrow = 1, ncol = 3 ) 如先前预期的那样，它们相当相关，并且可以同时进行分析。\n显然，从图表中可以看出，平均肿瘤半径为10至15毫米的患者被诊断为乳腺癌的概率更高。\n模型 # 数据集分割 # 对于后续建模，我们需要将数据集随机分为两部分，一部分用于训练预测模型，另一部分用于测试模型的准确性。\nset.seed(123) # Set the repeatability set.seed() to ensure that it is repeatable train \u0026lt;- sample(nrow(data), 0.7 * nrow(data)) train_data \u0026lt;- data[train, ] test_data \u0026lt;- data[-train, ] train_data 表示训练数据，validate_data 代表验证数据\n逻辑回归建模 # 由于最终预测结果是0和1，因此不适宜使用线性回归\n这里我们选择使用逻辑回归的思想来构建模型\n逻辑回归中使用的连接函数是Sigmoid函数的最佳代表，即逻辑函数。\n从上述分析中，我们选择 radius 在 radius、perimeter 和 area 中用于建模。\nmodel \u0026lt;- glm( data = train_data, formula = diagnosis ~ mean_texture + mean_smoothness + mean_radius, family = binomial(link = \u0026#34;logit\u0026#34;) ) model \u0026lt;- step(model) # Carry out the step-by-step regression method for data analysis summary(model) Use summary (model) to view the model.\nCall: glm(formula = diagnosis ~ mean_texture + mean_smoothness + mean_radius, family = binomial(link = \u0026#34;logit\u0026#34;), data = train_data) Deviance Residuals: Min 1Q Median 3Q Max -2.91948 -0.03436 0.04781 0.21133 2.01672 Coefficients: Estimate Std. Error z value Pr(\u0026gt;|z|) (Intercept) 40.52957 5.09828 7.950 1.87e-15 *** mean_texture -0.34187 0.06622 -5.163 2.44e-07 *** mean_smoothness -140.35265 21.54005 -6.516 7.23e-11 *** mean_radius -1.36821 0.17827 -7.675 1.65e-14 *** --- Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1 (Dispersion parameter for binomial family taken to be 1) Null deviance: 515.0 on 397 degrees of freedom Residual deviance: 134.9 on 394 degrees of freedom AIC: 142.9 Number of Fisher Scoring iterations: 8 From the results of summary, it can be seen that the three variables we selected contribute significantly to the results.\nCalculate the fitting threshold # Here we use roc from pRoc to find the optimal threshold.\npre \u0026lt;- predict(model, type = \u0026#34;response\u0026#34;, train_data) modelroc \u0026lt;- roc(train_data$diagnosis, pre) plot(modelroc, print.auc = TRUE, auc.polygon = TRUE, grid = c(0.1, 0.2), grid.col = c(\u0026#34;green\u0026#34;, \u0026#34;red\u0026#34;), max.auc.polygon = TRUE, auc.polygon.col = \u0026#34;skyblue\u0026#34;, print.thres = TRUE ) 可以看出0.588是我们需要的阈值。考虑到这一点，我们选择0.6作为模型的阈值。\n测试集数据验证 # 在成功使用训练集数据构建模型后，我们还应该使用检查数据集来检查模型预测的准确性。由于预测是一个数字，而我们最终想要的是一个已确认或未诊断的结果，我们需要一个阈值来将预测值分类，以获得1或0的数值结果。\ntest_data$prob \u0026lt;- model %\u0026gt;% predict(type = \u0026#34;response\u0026#34;, newdata = test_data) test_data$prob \u0026lt;- ifelse(test_data$prob \u0026gt; 0.6, 1, 0) test_data$diff \u0026lt;- ifelse(test_data$diagnosis == test_data$prob, 1, 0) 评估模型的预测效果 # 我们可以绘制饼图来可视化模型的准确率。\ndiff_count \u0026lt;- test_data %\u0026gt;% count(diff, name = \u0026#34;count\u0026#34;) diff_count$diff \u0026lt;- ifelse(diff_count$diff == 0, \u0026#34;False\u0026#34;, \u0026#34;True\u0026#34;) diff_plot \u0026lt;- diff_count %\u0026gt;% ggplot(mapping = aes( x = 1, y = count, fill = factor(diff), )) diff_plot + geom_bar(stat = \u0026#34;identity\u0026#34;) + coord_polar(theta = \u0026#34;y\u0026#34;) + scale_x_continuous(name = NULL, breaks = NULL) + scale_y_continuous(name = NULL, breaks = NULL) + labs( x = \u0026#34;\u0026#34;, y = \u0026#34;\u0026#34;, fill = \u0026#34;\u0026#34;, title = \u0026#34;Model prediction accuracy\u0026#34;, ) + theme( legend.position = \u0026#34;top\u0026#34;, plot.title = element_text(hjust = 0.5, size = 14), # title position ) paste( round(100 * diff_count$count[2] / (diff_count$count[1] + diff_count$count[2]), 2), \u0026#34;%\u0026#34; ) [1] \u0026#34;93.57 %\u0026#34; 结果非常令人惊讶。我们模型的预测准确度极高。为了避免错误和移除预设的随机值，我尝试了许多次，并得到了超过90%的更好结果，这表明我们的模型稳定且准确。\nFull code library(tidyverse) library(ggplot2) library(corrplot) library(pROC) library(gridExtra) # Import the original data data \u0026lt;- read.csv(\u0026#34;Breast_cancer_data.csv\u0026#34;) head(data) # Check for missing data sum(is.na(data)) # Redundant data view duplicated_count \u0026lt;- sum(duplicated(data)) # Analyze the distribution of each variable rel_area \u0026lt;- ggplot(data, aes(x = mean_area, y = ..density..)) + geom_histogram(fill = \u0026#34;blue\u0026#34;, color = \u0026#34;black\u0026#34;, size = 0.2, alpha = 0.2, bins = 30) + # nolint geom_density() rel_radius \u0026lt;- ggplot(data, aes(x = mean_radius, y = ..density..)) + geom_histogram(fill = \u0026#34;blue\u0026#34;, color = \u0026#34;black\u0026#34;, size = 0.2, alpha = 0.2, bins = 30) + # nolint geom_density() rel_texture \u0026lt;- ggplot(data, aes(x = mean_texture, y = ..density..)) + geom_histogram(fill = \u0026#34;blue\u0026#34;, color = \u0026#34;black\u0026#34;, size = 0.2, alpha = 0.2, bins = 30) + # nolint geom_density() rel_smooth \u0026lt;- ggplot(data, aes(x = mean_smoothness, y = ..density..)) + geom_histogram(fill = \u0026#34;blue\u0026#34;, color = \u0026#34;black\u0026#34;, size = 0.2, alpha = 0.2, bins = 30) + # nolint geom_density() rel_perimeter \u0026lt;- ggplot(data, aes(x = mean_perimeter, y = ..density..)) + geom_histogram(fill = \u0026#34;blue\u0026#34;, color = \u0026#34;black\u0026#34;, size = 0.2, alpha = 0.2, bins = 30) + # nolint geom_density() grid.arrange(rel_area, rel_radius, rel_texture, rel_smooth, rel_perimeter, nrow = 3, ncol = 2 ) # Univariate box pattern analysis # mean_radius ggplot(data, aes(x = factor(diagnosis), y = mean_radius)) + geom_boxplot(outlier.colour = \u0026#34;blue\u0026#34;, outlier.shape = 5, outlier.size = 4) + labs(title = \u0026#34;Plot of mean_radius\u0026#34;, x = \u0026#34;diagnosis\u0026#34;) # mean_texture ggplot(data, aes(x = factor(diagnosis), y = mean_texture)) + geom_boxplot(outlier.colour = \u0026#34;blue\u0026#34;, outlier.shape = 5, outlier.size = 4) + labs(title = \u0026#34;Plot of mean_texture\u0026#34;, x = \u0026#34;diagnosis\u0026#34;) # mean_perimeter ggplot(data, aes(x = factor(diagnosis), y = mean_perimeter)) + geom_boxplot(outlier.colour = \u0026#34;blue\u0026#34;, outlier.shape = 5, outlier.size = 4) + labs(title = \u0026#34;Plot of mean_perimeter\u0026#34;, x = \u0026#34;diagnosis\u0026#34;) # mean_area ggplot(data, aes(x = factor(diagnosis), y = mean_area)) + geom_boxplot(outlier.colour = \u0026#34;blue\u0026#34;, outlier.shape = 5, outlier.size = 4) + labs(title = \u0026#34;Plot of mean_area\u0026#34;, x = \u0026#34;diagnosis\u0026#34;) # mean_smoothness ggplot(data, aes(x = factor(diagnosis), y = mean_smoothness)) + geom_boxplot(outlier.colour = \u0026#34;blue\u0026#34;, outlier.shape = 5, outlier.size = 4) + labs(title = \u0026#34;Plot of mean_smoothness\u0026#34;, x = \u0026#34;diagnosis\u0026#34;) # Correlation analysis between variables cor_analysis \u0026lt;- cor(data[c(1:5)]) corrplot(cor_analysis, method = \u0026#34;number\u0026#34;) # Relevance between variables and results # ----------------------------Related variables------------------------------ # # radius \u0026amp; texture rtPlot \u0026lt;- ggplot(data, aes( x = mean_radius, y = mean_texture, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) # radius \u0026amp; smoothness rsPlot \u0026lt;- ggplot(data, aes( x = mean_radius, y = mean_smoothness, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) # texture \u0026amp; perimeter tpPlot \u0026lt;- ggplot(data, aes( x = mean_texture, y = mean_perimeter, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) # texture \u0026amp; area taPlot \u0026lt;- ggplot(data, aes( x = mean_texture, y = mean_area, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) # texture \u0026amp; smoothness tsPlot \u0026lt;- ggplot(data, aes( x = mean_texture, y = mean_smoothness, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) # perimeter \u0026amp; smoothness psPlot \u0026lt;- ggplot(data, aes( x = mean_perimeter, y = mean_smoothness, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) # area \u0026amp; smoothness asPlot \u0026lt;- ggplot(data, aes( x = mean_area, y = mean_smoothness, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) grid.arrange(rtPlot, rsPlot, tpPlot, taPlot, tsPlot, psPlot, asPlot, nrow = 3, ncol = 3 ) # ---------------------------Strong related variable---------------------------- # # radius \u0026amp; perimeter rpPlot \u0026lt;- ggplot(data, aes( x = mean_radius, y = mean_perimeter, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) # radius \u0026amp; area raPlot \u0026lt;- ggplot(data, aes( x = mean_radius, y = mean_area, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) # perimeter \u0026amp; area paPlot \u0026lt;- ggplot(data, aes( x = mean_perimeter, y = mean_area, color = as.factor(diagnosis) )) + geom_point() + theme_minimal() + theme(legend.position = \u0026#34;none\u0026#34;) grid.arrange(rpPlot, raPlot, paPlot, nrow = 1, ncol = 3 ) # Dataset segmentation set.seed(123) # Set the repeatable set.seed() to ensure that it is repeatable train \u0026lt;- sample(nrow(data), 0.7 * nrow(data)) train_data \u0026lt;- data[train, ] test_data \u0026lt;- data[-train, ] # Logical regression modeling model \u0026lt;- glm( data = train_data, formula = diagnosis ~ mean_texture + mean_smoothness + mean_radius, family = binomial(link = \u0026#34;logit\u0026#34;) ) model \u0026lt;- step(model) # step-by-step regression method summary(model) # Export all results # Calculate the fitting threshold pre \u0026lt;- predict(model, type = \u0026#34;response\u0026#34;, train_data) modelroc \u0026lt;- roc(train_data$diagnosis, pre) plot(modelroc, print.auc = TRUE, auc.polygon = TRUE, grid = c(0.1, 0.2), grid.col = c(\u0026#34;green\u0026#34;, \u0026#34;red\u0026#34;), max.auc.polygon = TRUE, auc.polygon.col = \u0026#34;skyblue\u0026#34;, print.thres = TRUE ) # Test set data verification test_data$prob \u0026lt;- model %\u0026gt;% predict(type = \u0026#34;response\u0026#34;, newdata = test_data) test_data$prob \u0026lt;- ifelse(test_data$prob \u0026gt; 0.6, 1, 0) test_data$diff \u0026lt;- ifelse(test_data$diagnosis == test_data$prob, 1, 0) # Test set data forecast statistics percentage diff_count \u0026lt;- test_data %\u0026gt;% count(diff, name = \u0026#34;count\u0026#34;) diff_count$diff \u0026lt;- ifelse(diff_count$diff == 0, \u0026#34;False\u0026#34;, \u0026#34;True\u0026#34;) diff_plot \u0026lt;- diff_count %\u0026gt;% ggplot(mapping = aes( x = 1, y = count, fill = factor(diff), )) diff_plot + geom_bar(stat = \u0026#34;identity\u0026#34;) + coord_polar(theta = \u0026#34;y\u0026#34;) + scale_x_continuous(name = NULL, breaks = NULL) + scale_y_continuous(name = NULL, breaks = NULL) + labs( x = \u0026#34;\u0026#34;, y = \u0026#34;\u0026#34;, fill = \u0026#34;\u0026#34;, title = \u0026#34;Model prediction accuracy\u0026#34;, ) + theme( legend.position = \u0026#34;top\u0026#34;, plot.title = element_text(hjust = 0.5, size = 14), ) paste( round(100 * diff_count$count[2] / (diff_count$count[1] + diff_count$count[2]), 2), \u0026#34;%\u0026#34; ) ","date":"2022-06-22","externalUrl":null,"permalink":"/posts/breast-cancer-prediction/","section":"博客","summary":"数据来源：乳腺癌预测数据集\n简介 # 全球范围内，乳腺癌是女性最常见的癌症类型，在死亡率方面排名第二。当发现异常肿块（来自自我检查或X光）或看到钙质小点（在X光片上）时，就会进行乳腺癌的诊断。在发现可疑肿块后，医生将进行诊断以确定是否为癌症，如果是，是否已扩散到身体的其他部位。\n","title":"乳腺癌预测模型","type":"posts"},{"content":"","date":"2022-06-22","externalUrl":null,"permalink":"/tags/%E6%95%B0%E6%8D%AE%E5%88%86%E6%9E%90/","section":"Tags","summary":"","title":"数据分析","type":"tags"},{"content":"数据来源：美国监狱死亡事件：_Dying Inside_的数据和关键发现\n包含美国750名及以上囚犯的大型监狱数据。为确保涵盖全国死亡人数，它还包括了每个州前10大监狱的数据\n涵盖2008年至2019年的523个监狱系统\n简介 # 美国政府不按监狱发布死亡率数据，使公众和政策制定者对死亡率高的设施处于黑暗之中。在首次此类统计中，路透社获得了这些数据并向公众发布。\n如果你们社区里的监狱死亡率异常高，但没有人知道呢？几十年来，全国各地的社区都面临着这种困境。司法部收集监狱死亡数据，但将信息锁起来，使得政策制定者、调查人员和活动家对问题设施一无所知。\n路透社记者提交了1500多项公开记录请求，以获取2008年至2019年该国最大监狱的死亡数据。今天，他们正逐个监狱、逐个州地公开这些信息。路透社审查了美国所有大型监狱，包括那些关押750名或以上囚犯的监狱。为确保审查覆盖全国，它还获得了每个州前10大监狱的数据。这些数据涵盖了523个监狱或监狱系统。\n美国大型监狱的死亡人数 # 使用到的包：tidyverse, ggplot2\n导入 # 第一步是将原始数据导入程序代码。\ndata_csv \u0026lt;- read.csv(\u0026#34;all_deaths.csv\u0026#34;) 筛选 # 我们希望对整个数据有一个直观的理解。目前我们不需要具体细节，只按年筛选数据。\ndeath_count \u0026lt;- data_csv %\u0026gt;% select(year) %\u0026gt;% count(year, name = \u0026#34;count\u0026#34;) %\u0026gt;% mutate(year = factor(year, levels = seq(2008, 20019, by = 1))) 请注意，在这个代码片段中，我们使用mutata函数将年份转换为因子，以便直方图的x轴坐标是散布的年份数据。\n绘图 # 我们选择了ggplot2来绘制精美直观的数据分析图像，使用年份作为x轴的参数。由于我们之前已经计算了每年出现的频率，我们只需要指定X和Y。\ndataplot \u0026lt;- death_count %\u0026gt;% ggplot(mapping = aes( x = year, y = count, )) geom_col() 由于数据展示不直观，我们为其添加颜色，并按照数据越大颜色越深的原理。 因为我们不需要标注颜色，所以我们添加了guides(fill = FALSE)语句。 然后我们在每个条形图中添加具体的数字显示，使图像直观且详细。 dataplot \u0026lt;- death_count %\u0026gt;% ggplot(mapping = aes( x = year, y = count, fill = -log(count), )) + guides(fill = FALSE) + geom_col() + geom_text(mapping = aes( label = count, )) 添加辅助信息 # 最后，我们添加辅助信息以扩展图表，包括标题、副标题和数据来源。然后微调标题位置并选择合适的字体，以进一步提升图像效果。\ndataplot + labs( x = NULL, y = \u0026#34;Death toll\u0026#34;, title = \u0026#34;Total number of deaths in large prisons in the United States\u0026#34;, subtitle = \u0026#34;death data from 2008 to 2019 in the nation\u0026#39;s biggest jails\u0026#34;, caption = \u0026#34;Data sources: https://www.reuters.com/investigates/special-report/usa-jails-graphic/\u0026#34;, # nolint ) + theme( plot.title = element_text(hjust = 0.5, size = 14), # title position text = element_text(family = \u0026#34;JetBrains Mono\u0026#34;), # font ) 研究结论 # 2008年至2019年间，美国大型监狱的死亡人数逐渐增加，从469人增至最多731人，并逐渐稳定在约700人左右。\nFull code library(tidyverse) library(ggplot2) # Import data_csv \u0026lt;- read.csv(\u0026#34;all_deaths.csv\u0026#34;) # data select death_count \u0026lt;- data_csv %\u0026gt;% select(year) %\u0026gt;% count(year, name = \u0026#34;count\u0026#34;) %\u0026gt;% mutate(year = factor(year, levels = seq(2008, 20019, by = 1))) # Plot dataplot \u0026lt;- death_count %\u0026gt;% ggplot(mapping = aes( x = year, y = count, fill = -log(count), )) + # guides(fill = FALSE) + geom_col() + geom_text(mapping = aes( label = count, )) # Add auxiliary information. dataplot + labs( x = NULL, y = \u0026#34;Death toll\u0026#34;, title = \u0026#34;Total number of deaths in large prisons in the United States\u0026#34;, subtitle = \u0026#34;death data from 2008 to 2019 in the nation\u0026#39;s biggest jails\u0026#34;, caption = \u0026#34;Data sources: https://www.reuters.com/investigates/special-report/usa-jails-graphic/\u0026#34;, # nolint ) + theme( legend.position = \u0026#34;none\u0026#34;, plot.title = element_text(hjust = 0.5, size = 14), # title position text = element_text(family = \u0026#34;JetBrains Mono\u0026#34;), # font ) 各州监狱死亡人数 # 在这个部分，我们试图进一步按州探索美国监狱死亡事件的细节\n导入 # 第一步是将原始数据导入程序代码。\ndata_csv \u0026lt;- read.csv(\u0026#34;all_deaths.csv\u0026#34;) 处理原始数据 # 由于我们需要每年每个州所有监狱的总死亡人数，我们首先使用table来计算相同的信息。然后我们将表格格式再次改为数据框形式，并更改索引名称以方便我们后续的绘图。\ndata_csv \u0026lt;- table(data_csv$year, data_csv$state) %\u0026gt;% as.data.frame() %\u0026gt;% rename(year = Var1, state = Var2, count = Freq) 绘图 # 根据上述数据处理，我们可以在图像上高效地绘制出各州大型监狱死亡人数的折线图，以方便后续分析。\ndata_plot \u0026lt;- data_csv %\u0026gt;% ggplot(mapping = aes( x = year, y = count, group = state, color = state, )) data_plot + geom_line() + labs( x = NULL, y = \u0026#34;Death toll\u0026#34;, title = \u0026#34;Prison deaths by state in the United States\u0026#34;, subtitle = \u0026#34;death data from 2008 to 2019 in the nation\u0026#39;s biggest jails\u0026#34;, caption = \u0026#34;Data sources: https://www.reuters.com/investigates/special-report/usa-jails-graphic/\u0026#34;, # nolint ) + theme( plot.title = element_text(hjust = 0.6, size = 14), # title position text = element_text(family = \u0026#34;JetBrains Mono\u0026#34;), # font ) 研究结论 # 可以清楚地看到，大部分数据曲线都聚集在一个地方，猜测是因为监狱的规模相似。 四个州的数据非常引人注目： 加利福尼亚 佛罗里达 德克萨斯 宾夕法尼亚 上文提到的四个州的数据远远超过其他州。合理推测可能存在更多更大的监狱，并且可能有相对较高的犯罪率。 Full code library(tidyverse) library(ggplot2) data_csv \u0026lt;- read.csv(\u0026#34;all_deaths.csv\u0026#34;) data_csv \u0026lt;- table(data_csv$year, data_csv$state) %\u0026gt;% as.data.frame() %\u0026gt;% rename(year = Var1, state = Var2, count = Freq) data_plot \u0026lt;- data_csv %\u0026gt;% ggplot(mapping = aes( x = year, y = count, group = state, color = state, )) data_plot + geom_line() + labs( x = NULL, y = \u0026#34;Death toll\u0026#34;, title = \u0026#34;Prison deaths by state in the United States\u0026#34;, subtitle = \u0026#34;death data from 2008 to 2019 in the nation\u0026#39;s biggest jails\u0026#34;, caption = \u0026#34;Data sources: https://www.reuters.com/investigates/special-report/usa-jails-graphic/\u0026#34;, # nolint ) + theme( plot.title = element_text(hjust = 0.6, size = 14), # title position text = element_text(family = \u0026#34;JetBrains Mono\u0026#34;), # font ) ","date":"2022-06-21","externalUrl":null,"permalink":"/posts/jail-deaths-in-america/","section":"博客","summary":"数据来源：美国监狱死亡事件：_Dying Inside_的数据和关键发现\n包含美国750名及以上囚犯的大型监狱数据。为确保涵盖全国死亡人数，它还包括了每个州前10大监狱的数据\n","title":"美国监狱死亡情况","type":"posts"},{"content":"Data source: Top 50 Most Followed Twitter Accounts\n简介 # 数据列出了Twitter上最受关注的50个账户，每个总数四舍五入到最近的十万，以及每个用户的职业或活动。账户总数和排名月度变化最后更新于2022年5月12日。\n粉丝排行榜 # 我们试图使用这个数据集制作推特粉丝前50名账户的直观图表\n导入 # 第一步是将原始数据导入程序代码。\ndata_csv \u0026lt;- read.csv(\u0026#34;Top 50 Most Followed Twitter Accounts.csv\u0026#34;) 可视化 # 由于Twitter账号ID的非重复性，我们自然选择了用户ID作为y轴数据。 我们按照粉丝数量重新排列账号，并在图像上从多到少显示。 为了使图像比较更直观，我们创造性地使用粉丝数量来绘制渐变色，从深到浅代表粉丝数量从多到少。 dataplot \u0026lt;- data_csv %\u0026gt;% ggplot(mapping = aes( x = Followers..millions., y = reorder(Account.username, Followers..millions.), fill = -log(Followers..millions.), )) + geom_bar( stat = \u0026#34;identity\u0026#34;, ) + guides(fill = \u0026#34;none\u0026#34;) + geom_text(mapping = aes( label = Followers..millions., )) # Add auxiliary information. dataplot + labs( x = \u0026#34;Followers (Millions)\u0026#34;, y = \u0026#34;Username\u0026#34;, title = \u0026#34;Top 50 in Twitter\u0026#34;, subtitle = \u0026#34;Information was last updated on May 12, 2022.\u0026#34;, caption = \u0026#34;Data sources: https://www.kaggle.com/datasets/hassanshehzadk/top-50-most-followed-twitter-accounts?resource=download\u0026#34;, ) + theme( plot.title = element_text(hjust = 0.4, size = 14), # title position panel.grid.minor = element_blank(), # Secondary grid lines text = element_text(family = \u0026#34;Hack Nerd Font\u0026#34;), # font axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1) ) Full code library(tidyverse) library(ggplot2) # Import data_csv \u0026lt;- read.csv(\u0026#34;Top 50 Most Followed Twitter Accounts.csv\u0026#34;) # Plot dataplot \u0026lt;- data_csv %\u0026gt;% ggplot(mapping = aes( x = Followers..millions., y = reorder(Account.username, Followers..millions.), fill = -log(Followers..millions.), )) + geom_bar( stat = \u0026#34;identity\u0026#34;, ) + guides(fill = \u0026#34;none\u0026#34;) + geom_text(mapping = aes( label = Followers..millions., )) # Add auxiliary information. dataplot + labs( x = \u0026#34;Followers (Millions)\u0026#34;, y = \u0026#34;Username\u0026#34;, title = \u0026#34;Top 50 in Twitter\u0026#34;, subtitle = \u0026#34;Information was last updated on May 12, 2022.\u0026#34;, caption = \u0026#34;Data sources: https://www.kaggle.com/datasets/hassanshehzadk/top-50-most-followed-twitter-accounts?resource=download\u0026#34;, # nolint ) + theme( plot.title = element_text(hjust = 0.4, size = 14), # title position panel.grid.minor = element_blank(), # Secondary grid lines text = element_text(family = \u0026#34;Hack Nerd Font\u0026#34;), # font axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1) ) 账户归属分析 # 我们还想了解拥有大量粉丝的账户的国家归属，因此绘制一个饼图来检查分布情况\n导入 # 第一步是将原始数据导入程序代码。\ndata_csv \u0026lt;- read.csv(\u0026#34;Top 50 Most Followed Twitter Accounts.csv\u0026#34;) 选择 # 快速统计数据集中每个国家出现的频率。\narea_count \u0026lt;- data_csv %\u0026gt;% count(Country, name = \u0026#34;count\u0026#34;) 可视化 # 由于ggplot中没有内置的饼图绘制方法，我们使用geom_bar和coord_polar来尝试达到相同的效果。 dataplot \u0026lt;- area_count %\u0026gt;% ggplot(mapping = aes( x = 1, y = count, fill = Country, )) dataplot + geom_bar(stat = \u0026#34;identity\u0026#34;) + coord_polar(theta = \u0026#34;y\u0026#34;) + scale_x_continuous(name = NULL, breaks = NULL) + scale_y_continuous(name = NULL, breaks = NULL) + scale_fill_viridis_d(option = \u0026#34;inferno\u0026#34;) 研究结论 # 显然，作为美国的本土软件，考虑到美国庞大的人口基数，属于美国的账户所在国家的数量远超其他国家。 作为一个人口众多的国家，印度意外地成为了美国的第二位。 其他国家的数量基本上是相同的。 Full code library(tidyverse) library(ggplot2) data_csv \u0026lt;- read.csv(\u0026#34;Top 50 Most Followed Twitter Accounts.csv\u0026#34;) area_count \u0026lt;- data_csv %\u0026gt;% count(Country, name = \u0026#34;count\u0026#34;) dataplot \u0026lt;- area_count %\u0026gt;% ggplot(mapping = aes( x = 1, y = count, fill = Country, )) dataplot + geom_bar(stat = \u0026#34;identity\u0026#34;) + coord_polar(theta = \u0026#34;y\u0026#34;) + scale_x_continuous(name = NULL, breaks = NULL) + scale_y_continuous(name = NULL, breaks = NULL) + scale_fill_viridis_d(option = \u0026#34;inferno\u0026#34;) + labs( x = \u0026#34;Followers (Millions)\u0026#34;, y = \u0026#34;Username\u0026#34;, fill = \u0026#34;Country\u0026#34;, title = \u0026#34;Country of Account\u0026#34;, subtitle = \u0026#34;Calculate the top 50 fan accounts on Twitter.\\nInformation was last updated on May 12, 2022.\u0026#34;, # nolint caption = \u0026#34;Data sources: https://www.kaggle.com/datasets/hassanshehzadk/top-50-most-followed-twitter-accounts?resource=download\u0026#34;, # nolint ) + theme( plot.title = element_text(hjust = 0.6, size = 14), # title position axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1), plot.caption = element_text(hjust = 0.3), ) ","date":"2022-06-20","externalUrl":null,"permalink":"/posts/top-50-twitter-accounts/","section":"博客","summary":"Data source: Top 50 Most Followed Twitter Accounts\n简介 # 数据列出了Twitter上最受关注的50个账户，每个总数四舍五入到最近的十万，以及每个用户的职业或活动。账户总数和排名月度变化最后更新于2022年5月12日。\n","title":"粉丝最多的50个推特号","type":"posts"},{"content":"数据来源：Carbon Dioxide Emission Estimates\n简介 # 数据来源于undata。最后更新于2021年11月1日。它包含了几年来世界各国总碳排放量和人均碳排放量。由于国家数量众多，在本数据分析中，我们仅选择了九个国家，即中国、美国、法国、德国、加拿大、意大利、日本、英国和奥地利。\n绘制图像 # 我们希望对这九个国家的数据有直观了解，所以选择在同一个图表中绘制\n导入 # 第一步是将原始数据导入程序代码。\ndata_csv \u0026lt;- read.csv(\u0026#34;SYB64_310_202110_Carbon Dioxide Emission Estimates.csv\u0026#34;) 数据清洗 # 我们需要从数据集中筛选出这九个国家的数据，为了能够进行比较，我们只需要人均数据，而不是总体数据。\nworld_data \u0026lt;- data_csv %\u0026gt;% filter(Country %in% c(\u0026#34;China\u0026#34;, \u0026#34;United States of America\u0026#34;, \u0026#34;United Kingdom\u0026#34;, \u0026#34;France\u0026#34;, \u0026#34;Germany\u0026#34;, \u0026#34;Australia\u0026#34;, \u0026#34;Japan\u0026#34;, \u0026#34;Canada\u0026#34;, \u0026#34;Italy\u0026#34;)) %\u0026gt;% filter(Series == \u0026#34;Emissions per capita (metric tons of carbon dioxide)\u0026#34;) 可视化 # 只需要按国家、年份作为 x 坐标，以及人均排放量作为 y 坐标来绘制数据集。\nworld_plot \u0026lt;- world_data %\u0026gt;% ggplot(mapping = aes( x = factor(Year), y = as.numeric(Value), color = Country, fill = Country, group = Country, )) world_plot + geom_point() + geom_line() + labs( x = NULL, y = \u0026#34;Emissions per capita (metric tons of carbon dioxide)\u0026#34;, title = \u0026#34;Per capita emissions of some countries\u0026#34;, subtitle = \u0026#34;Data from 1975 to 2018\u0026#34;, caption = \u0026#34;Data sources: http://data.un.org/default.aspx\u0026#34;, ) + theme( plot.title = element_text(size = 14), # title position text = element_text(family = \u0026#34;JetBrains Mono\u0026#34;), # font ) 研究结论 # 总的来说，自 2015 年以来，各国的排放量趋于平稳。 自 1975 年以来，各国人均碳排放量呈现增减交替的趋势，并趋于稳定。 总的来说，澳大利亚、加拿大和美国的人均碳排放量远远超过其他国家。 Full code library(tidyverse) library(ggplot2) data_csv \u0026lt;- read.csv(\u0026#34;SYB64_310_202110_Carbon Dioxide Emission Estimates.csv\u0026#34;) world_data \u0026lt;- data_csv %\u0026gt;% filter(Country %in% c(\u0026#34;China\u0026#34;, \u0026#34;United States of America\u0026#34;, \u0026#34;United Kingdom\u0026#34;, \u0026#34;France\u0026#34;, \u0026#34;Germany\u0026#34;, \u0026#34;Australia\u0026#34;, \u0026#34;Japan\u0026#34;, \u0026#34;Canada\u0026#34;, \u0026#34;Italy\u0026#34;)) %\u0026gt;% filter(Series == \u0026#34;Emissions per capita (metric tons of carbon dioxide)\u0026#34;) world_plot \u0026lt;- world_data %\u0026gt;% ggplot(mapping = aes( x = factor(Year), y = as.numeric(Value), color = Country, fill = Country, group = Country, )) world_plot + geom_point() + geom_line() + labs( x = NULL, y = \u0026#34;Emissions per capita (metric tons of carbon dioxide)\u0026#34;, title = \u0026#34;Per capita emissions of some countries\u0026#34;, subtitle = \u0026#34;Data from 1975 to 2018\u0026#34;, caption = \u0026#34;Data sources: http://data.un.org/default.aspx\u0026#34;, ) + theme( plot.title = element_text(size = 14), # title position text = element_text(family = \u0026#34;JetBrains Mono\u0026#34;), # font ) 按国家划分的数据图 # 可视化 # 我们只需要在上述基础上添加一个语句来按国家分隔图表。 同时，由于国家数据已经包含在各种图表中，我们不需要额外的图例。 world_plot \u0026lt;- world_data %\u0026gt;% ggplot(mapping = aes( x = factor(Year), y = as.numeric(Value), color = Country, fill = Country, group = Country, )) world_plot + geom_point() + geom_line() + facet_wrap(~Country) + labs( x = NULL, y = \u0026#34;Emissions per capita (metric tons of carbon dioxide)\u0026#34;, title = \u0026#34;Per capita emissions of some countries\u0026#34;, subtitle = \u0026#34;Data from 1975 to 2018\u0026#34;, caption = \u0026#34;Data sources: http://data.un.org/default.aspx\u0026#34;, ) + theme( legend.position = \u0026#34;none\u0026#34;, plot.title = element_text(size = 14), # title position text = element_text(family = \u0026#34;JetBrains Mono\u0026#34;), # font ) 研究结论 # 加拿大、法国、德国、意大利和日本整体上变化不大。 美国近年来持续下降，而中国正在上升。 Full code library(tidyverse) library(ggplot2) data_csv \u0026lt;- read.csv(\u0026#34;SYB64_310_202110_Carbon Dioxide Emission Estimates.csv\u0026#34;) world_data \u0026lt;- data_csv %\u0026gt;% filter(Country %in% c(\u0026#34;China\u0026#34;, \u0026#34;United States of America\u0026#34;, \u0026#34;United Kingdom\u0026#34;, \u0026#34;France\u0026#34;, \u0026#34;Germany\u0026#34;, \u0026#34;Australia\u0026#34;, \u0026#34;Japan\u0026#34;, \u0026#34;Canada\u0026#34;, \u0026#34;Italy\u0026#34;)) %\u0026gt;% filter(Series == \u0026#34;Emissions per capita (metric tons of carbon dioxide)\u0026#34;) world_plot \u0026lt;- world_data %\u0026gt;% ggplot(mapping = aes( x = factor(Year), y = as.numeric(Value), color = Country, fill = Country, group = Country, )) world_plot + geom_point() + geom_line() + facet_wrap(~Country) + labs( x = NULL, y = \u0026#34;Emissions per capita (metric tons of carbon dioxide)\u0026#34;, title = \u0026#34;Per capita emissions of some countries\u0026#34;, subtitle = \u0026#34;Data from 1975 to 2018\u0026#34;, caption = \u0026#34;Data sources: http://data.un.org/default.aspx\u0026#34;, ) + theme( legend.position = \u0026#34;none\u0026#34;, plot.title = element_text(size = 14), # title position text = element_text(family = \u0026#34;JetBrains Mono\u0026#34;), # font ) ","date":"2022-06-19","externalUrl":null,"permalink":"/posts/carbon-dioxide-emission-estimates/","section":"博客","summary":"数据来源：Carbon Dioxide Emission Estimates\n简介 # 数据来源于undata。最后更新于2021年11月1日。它包含了几年来世界各国总碳排放量和人均碳排放量。由于国家数量众多，在本数据分析中，我们仅选择了九个国家，即中国、美国、法国、德国、加拿大、意大利、日本、英国和奥地利。\n","title":"二氧化碳排放量估算","type":"posts"},{"content":"","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"亲身体验过的各类让我印象深刻的产品，有的产品还在使用，另一些可能已经寿终正寝，亦或是转手卖出，也可能出于各种原因没有继续使用，但全部记录在此（按入手时间倒序），作为赛博纪念馆😄。\n","externalUrl":null,"permalink":"/goods/","section":"好物分享","summary":"亲身体验过的各类让我印象深刻的产品，有的产品还在使用，另一些可能已经寿终正寝，亦或是转手卖出，也可能出于各种原因没有继续使用，但全部记录在此（按入手时间倒序），作为赛博纪念馆😄。\n","title":"好物分享","type":"goods"}]