由 DrivenData 提供
为什么要重视项目结构?
说起数据分析, 我们往往会想到报告结果, 深入见解或可视化. 通常这些最终结果占据了主要地位, 所以人们很容易专注于让结果看起来漂亮而忽略了生成它们的代码质量. 但是, 这些最终结果都是以编程方式创建的, 所以代码质量仍然很重要! 此处我们讨论的不是代码缩进或格式标准, 数据科学的代码质量的最终标准是正确性和可再现性(reproducibility).
众所周知, 好的分析通常是随意和偶然探索的结果. 各种没得到结果的探索性实验和快速测试都是通往好结果道路上的一部分, 并且没有灵丹妙药可以将数据探索转变为简单的线性过程.
一旦开始一个项目, 就很难再去思考代码结构和项目布局了. 所以最好从一个干净, 合乎逻辑的结构开始并一以贯之. 我们认为使用这样的标准化设置是非常有好处的. 原因如下:
其他人会感谢你
定义明确的标准项目结构意味着新手无需研究大量文档就可以理解一项分析. 这也意味着他们不一定非得阅读 100%的代码才知道去哪里找特定的内容.
组织良好的代码往往能做到自我记录(self-documenting), 组织结构本身可以在无需太多开销的情况下为你的代码提供上下文. 人们会因此感谢你, 因为他们可以:
● 更轻松地与你在此分析中合作
● 从你对流程和领域的分析中学习
● 对分析得到的结论充满信心
你可以在任何主流的 web 开发框架 (如 Django 或 Ruby on Rails) 中找到这方面的好例子. 在创建一个新的 Rails 项目之前, 没有人会去思考要在哪个位置放什么, 他们只是运行 Rails new 来获得像其他人一样的标准项目骨架(skeleton). 由于该默认结构在大多数项目中都是合乎逻辑且合理的, 因此从未见过该特定项目的人也可以容易地找到各种部件.
另一个很好的例子是类 Unix 系统的文件系统层次结构标准 (Filesystem Hierarchy Standard)./ etc 目录有非常特定的目的, 就像 / tmp 文件夹一样, 每个人(或多或少) 都同意遵守该约定. 这意味着 Red Hat 用户和 Ubuntu 用户都知道在哪里查找某些类型的文件, 即使他们使用的是对方的系统或者其他任何符合该标准的系统!
理想情况下, 当同事打开您的数据科学项目时, 也应该如此.
你会感谢自己
你尝试过重现几个月前甚至几年前做的分析吗? 你可能编写了代码, 但现在却不知道是否应该使用 make_figures.py.old,make_figures_working.py 或者 new_make_figures01.py 来完成工作. 以下是我们的一些问题:
● 在开始之前, 是否应该主动把 X 列加入到数据中? 还是说其中某个 notebook 可以完成这一步?
● 想一想, 在运行绘图代码之前我们必须首先运行哪个 notebook: 它是 "过程数据" 还是 "干净数据"?
● 地理图形中所用的 shapefiles 是从哪下载的?
● 等类似问题
这些问题让人头疼, 并且是无组织项目的症状. 良好的项目结构应该让人很容易回到旧时的工作, 例如分离关注点, 将分析抽象为 DAG, 以及版本控制等实践.
没有任何约束
不赞同某些默认文件夹名称? 正在做一个不标准且与当前结构不完全匹配的项目? 更愿意使用与 (少数) 默认包不同的包?
去吧! 这是一种轻量级结构, 旨在成为许多项目的良好起点. 正如 PEP 8 所说:
项目内部的一致性更为重要. 一个模块或功能内部的一致性是最重要的.... 但是, 要知道何时不一致, 有时风格指南建议并不适用. 如有疑问, 请用你的最佳判断. 查看其他示例并确定最佳效果. 并且不要犹豫去提问!
开始
我们为 Python 项目创建了一个数据科学 cookiecutter 模板. 您的分析不一定要在 Python 中, 但模板确实提供了一些 Python 样板, 您可能想要删除它们(例如, 在 src 文件夹中, 以及 docs 中的 Sphinx 文档框架).
需求
● Python 2.7 或 3.5
● cookiecutter Python package>= 1.4.0: pip install cookiecutter
开始一个新项目
启动新项目只需在命令行中运行如下命令. 无需先创建目录, cookiecutter 将为您完成.
- cookiecutter
- https://GitHub.com/drivendata/cookiecutter-data-science
示例
原文中是一段视频, 建议从原文链接中观看.
- # OPTIONAL: Load the "autoreload" extension so that code can change
- %load_ext autoreload
- # OPTIONAL: always reload modules so that as you change code in src, it gets loaded
- %autoreload 2
- from src.data import make_dataset
- # example .env file
- DATABASE_URL=postgres://username:password@localhost:5432/dbname
- AWS_ACCESS_KEY=myaccesskey
- AWS_SECRET_ACCESS_KEY=mysecretkey
- OTHER_VARIABLE=something
- # src/data/dotenv_example.py
- import os
- from dotenv import load_dotenv, find_dotenv
- # find .env automagically by walking up directories until it's found
- dotenv_path = find_dotenv()
- # load up the entries as environment variables
- load_dotenv(dotenv_path)
- database_url = os.environ.get("DATABASE_URL")
- other_variable = os.environ.get("OTHER_VARIABLE")
- [default]
- aws_access_key_id=myaccesskey
- aws_secret_access_key=mysecretkey
- [another_project]
- aws_access_key_id=myprojectaccesskey
- aws_secret_access_key=myprojectsecretkey
来源: https://yq.aliyun.com/articles/647003