数据科学中的的十大编码错误

翻译:疯狂的技术宅html

原文:towardsdatascience.com/top-10-codi…python

数据科学家是“比任何软件工程师都更擅长统计数据的人,并且比任何统计学家都更擅长软件工程”。许多数据科学家都有统计学背景,而且在软件工程方面经验不多。我是一名高级数据科学家,在 Stackoverflow 上的 python 板块排名前 1%,并与许多(初级)数据科学家合做。如下是我常常看到的 10 个常见错误列表。git

1. 不共享代码中引用的数据

数据科学须要代码和数据。所以为了让其余人可以重现你的结果,他们须要可以访问数据。但不少人忘记了共享他们的代码用到的数据。github

import pandas as pd
df1 = pd.read_csv('file-i-dont-have.csv') # fails
do_stuff(df)
复制代码

解决方案:使用 d6tpipe与 你的代码共享数据文件或上传到 S三、web、google drive 等或保存到数据库,以便他人能够检索文件(但不要不要把它们添加到 git 中,见下文)。web

2. 对没法访问的路径作了硬编码

与错误 1 相似,若是你对其余人无权访问的路径进行了硬编码,那么他们没法运行你的代码而且必须检查许多地方以手动更改路径。 Booo!数据库

import pandas as pd
df = pd.read_csv('/path/i-dont/have/data.csv') # fails
do_stuff(df)
# or 
impor os
os.chdir('c:\\Users\\yourname\\desktop\\python') # fails
复制代码

解决方案:使用相对路径、全局路径配置变量或 d6tpipe 使你的数据易于访问。apache

3. 将数据与代码混在一块儿

因为数据科学的代码须要数据,为何不把它们放在一块儿呢?不过当你在查看本身项目的时候,会发现数据文件、图片、输出结果和其余垃圾文件混在一块儿。哎呀,真是一团糟!bash

├── data.csv
├── ingest.py
├── other-data.csv
├── output.png
├── report.html
└── run.py
复制代码

解决方案:将你的目录按照类别进行组织,如数据、报告、代码等。请参阅Cookiecutter数据科学d6tflow 项目模板 并使用第一条中提到的工具来存储和共享数据。cookie

4. 用 Git 把数据和源代码一块儿提交

大多数人如今对他们的代码进行版本控制(若是你不这样作那就是另外一个错误!!见git)。在共享数据时,可能很容易将数据文件添加到版本控制中。这对于很是小的文件是能够的,可是 git 没有针对数据进行优化,尤为是大文件。app

git add data.csv
复制代码

解决方案:使用第一条中提到的工具来存储和共享数据。若是你真的想要用版本控制系统去管理数据,请参阅d6tpipeDVCGit 大文件存储

5. 编写函数而不是 DAG

关于数据的问题够多了,接下来让咱们谈谈实际的代码!因为你在学习编码时第一个学到的就是函数,所以数据科学代码主要被组织为一系列线性运行的函数。这样会致使一些问题,请参阅机器学习代码出问题的4个缘由

def process_data(data, parameter):
    data = do_stuff(data)
    data.to_pickle('data.pkl')
data = pd.read_csv('data.csv')
process_data(data)
df_train = pd.read_pickle(df_train)
model = sklearn.svm.SVC()
model.fit(df_train.iloc[:,:-1], df_train['y'])
复制代码

**解决方案:**数据科学代码不是对函数进行线性连接,而是更好地写为一组具备依赖关系的任务。使用 d6tflowairflow

6. 过多的依赖循环

与函数同样,for 循环是学习编码时学到的第一件事。这容易理解,但它们很慢并且过于冗长,这只能说明你不知道矢量化,而用循环来进行替代。

x = range(10)
avg = sum(x)/len(x); std = math.sqrt(sum((i-avg)**2 for i in x)/len(x));
zscore = [(i-avg)/std for x]
# should be: scipy.stats.zscore(x)
# or
groupavg = []
for i in df['g'].unique():
	dfg = df[df[g']==i]
	groupavg.append(dfg['g'].mean())
# should be: df.groupby('g').mean()
复制代码

解决方案Numpyscipypandas 能够帮你把不少你认为可能须要循环的工做矢量化。

7. 不写单元测试

随着数据、参数或用户输入的变化,你的代码可能会发生异常中断,你可能不会注意这点,可是这可能致使输出错误,若是有人根据你的输出作出决定,那么糟糕的数据将会致使错误的决策!

**解决方案:**使用 assert 语句检查数据质量。 pandas 有相似的测试,也能够用 d6tstack 检查数据提取和 d6tjoin 对数据链接进行。代码示例数据检查:

assert df['id'].unique().shape[0] == len(ids) # have data for all ids?
assert df.isna().sum()<0.9 # catch missing values
assert df.groupby(['g','date']).size().max() ==1 # no duplicate values/date?
assert d6tjoin.utils.PreJoin([df1,df2],['id','date']).is_all_matched() # all ids matched?
复制代码

8. 不给代码加注释

我明白了,你急着作一些分析。你把事情搞混在一块儿,把结果交给你的客户或老板。而后一个星期后,他们回来讲“你能改变xyz”或“你能更新吗”。你看看你的代码,不记得你为何作了你作的。如今想象其余人必须运行它。

def some_complicated_function(data):
	data = data[data['column']!='wrong']
	data = data.groupby('date').apply(lambda x: complicated_stuff(x))
	data = data[data['value']<0.9]
	return data
复制代码

解决方案:即便在你提供数据分析的代码以后,也要花费额外的时间来对你的所做所为进行注释。你会感谢本身,一样别人也会这样作!这使你看起来更像专业人士!

9. 将数据保存为 csv 或 pickle 格式

再回到数据,毕竟这是数据科学。就像函数和 for 循环同样,CSV 和 pickle 文件格式也是经常使用的,但实际上它们并非很好。 CSV 不包含结构,所以别人必须再次解析数字和日期。尽管 Pickles 解决了这个问题,但只能在 python 中使用并且不会被压缩。二者都不是存储大型数据集的好格式。

def process_data(data, parameter):
    data = do_stuff(data)
    data.to_pickle('data.pkl')
data = pd.read_csv('data.csv')
process_data(data)
df_train = pd.read_pickle(df_train)
复制代码

解决方案:使用 parquet 格式或其余二进制数据格式与数据模式,在合适的状况下压缩数据。 d6tflow 能自动将任务的数据输出保存为 parquet 格式,所以你无需另行处理。

10. 使用 jupyter notebook

这是一个有争议的结论:jupyter 笔记本和 CSV 同样广泛,不少人都在用它,这并不意味着它是合适的。 Jupyter notebook 形成了上面提到的许多不良软件工程的习惯,特别是:

  1. 你很想将全部文件保存到同一个目录中
  2. 编写运行于上下文代码关系而不是 DAG 的代码
  3. 你没有把你的代码模块化
  4. 难以调试
  5. 代码和输出混在同一个文件中
  6. 没有良好的版本控制

Solution: Use pycharm and/or spyder.

解决方案:使用 pycharmspyder

相关文章
相关标签/搜索