数据科学从业者常见的不良小习惯

数据科学从业者常见的不良小习惯

Norm Niemer 京东云开发者社区  前天

image

选自Medium

京东云开发者社区编译

数据科学家是“比任何软件工程师都更擅长统计数据,比统计学家更擅长软件工程的一批人”。许多数据科学家都有统计学背景,同时也有着一些软件工程方面经验。我是一名在Stackoverflow上使用Python代码排名前1%的高级数据科学家,并与许多(初级)数据科学家们一起工作。在这个过程中,我发现大家其实都或多或少有着一些不太好的小习惯,以下是我列出的10个数据科学从业者常见的不良习惯列表。

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

数据科学需要代码和数据,这点毋庸置疑。因此,如果别人要查证到你的结果,他们就需要访问数据。这看起来似乎很基本,但很多人都会忘记共享他们代码中引用数据。

1import pandas as pd
2df1 = pd.read_csv('file-i-dont-have.csv') # fails
3do_stuff(df)

解决方案:使用d6tpipe(https://github.com/d6t/d6tpipe)来共享您的代码数据文件或将其上传到S3/Web/Google Drive等,或者保存到数据库也可以。这样做的目的在于可以便于大家进行文件检索。(Notice:但不要将它们添加到Git,详情见下文)。

2.硬编码无法访问的路径

与错误1类似,如果您的硬编码路径别人无权访问,那他们则无法运行您的代码并且必须查看许多地方以手动更改路径。🙄🙄🙄!

1import pandas as pd2df = pd.read_csv('/path/i-dont/have/data.csv') # fails3do_stuff(df)4# or 5impor os6os.chdir('c:\\Users\\yourname\\desktop\\python') # fails

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

3.将数据与代码混在一起

有人会问,由于数据科学代码需要数据,因此为什么不将它们转存到同一目录中呢?但这也意味着,当你在使用它的时候,你的图像、报告和其他垃圾也都会存在里面。Emm……可以说是一团糟呢!

1├── data.csv
2├── ingest.py
3├── other-data.csv
4├── output.png
5├── report.html
6└── run.py

解决方案:将您的目录进行分类,如数据、报告、代码等。具体请参阅Cookiecutter Data Science或d6tflow项目模板(https://github.com/d6t/d6tflow-template)。(可用本文第1点中提到的工具来存储和共享数据。)

4. 使用Git提交源代码数据

大多数人现在用版本控制系统来管理他们的代码(如果你不这样的话,那将会是另一个错误!!🙂)。在尝试共享数据时,可能很容易将数据文件添加到版本控制中。这对于非常小的文件是可以的,但是git没有针对数据进行优化,尤其是大文件。

1git add data.csv

解决方案:建议使用第1点中提到的工具来存储和共享数据。如果您真的想要版本控制系统来数据,请参阅d6tpipe,DVC和Git大文件存储。

5.编写函数而不是DAGs

聊完数据相关的内容后,让我们来谈谈实际的代码部分!由于您在学习编码时学到的第一件事就是函数,因此数据科学代码主要被组织为一系列线性运行的函数。

1def process_data(data,parameter):
2    data = do_stuff(data)
3    data.to_pickle('data.pkl')
4data = pd.read_csv('data.csv')
5process_data(data)6df_train = pd.read_pickle(df_train)
7model = sklearn.svm.SVC()
8model.fit(df_train.iloc [:,:-  1],df_train [ 'Y'])

解决方案:数据科学代码不是线性地链接函数,而是更好地编写为一组具有它们之间依赖关系的任务。

6.写入循环

与函数一样,for循环是学习编码时学到的第一件事。这个东西不难理解,但它们很慢而且过于冗长,如果你使用他们,通常就表明你并没有发现矢量化的替代方案。

1x = range(10) 
2avg = sum(x)/len(x); std = math.sqrt(sum((i-avg)**2 for i in x)/len(x)); 
3zscore = [(i-avg)/std for x] 4# should be: scipy.stats.zscore(x) 5# or 6groupavg = [] 7for i in df['g'].unique(): 8    dfg = df[df[g']==i] 9    groupavg.append(dfg['g'].mean())10# should be: df.groupby('g').mean()

解决方案:Numpy,Scipy和Pandas为您认为可能需要循环的大多数情况提供了矢量化函数,可随时进去拽去您需要的。

7.忘写单元测试

随着数据、参数或用户输入的变化,您的代码极有可能在根本没注意到时就出现输出错误的情况。如果有人根据您的输出结果做出决定,那么错误的数据将有可能导致错误的决策!

解决方案:使用Assert语句检查数据质量。Pandas也有相同的测试,d6tstack检查数据摄取和数据连接。数据检查代码示例如下:

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

8.没有记录代码

我能明白,你急着要做一些分析。于是,你把所有的数据、代码都放在一起,然后得出了结果交给你的客户或老板。一个星期后,他们回来说“你能改一下xyz”或“你能更新这部分内容吗?”。然后你看着你的代码,完全不记得你为什么这么做以及你怎么去做的了。你还敢想象其他人必须运行它这件事吗?

1    def some_complicated_function(data):
2    data = data[data['column']!='wrong']
3    data = data.groupby('date').apply(lambda x: complicated_stuff(x))
4    data = data[data['value']<0.9]5    return data

解决方案:即使在您提供分析结果之后,也请一定要花费一部分额外的时间来记录您的操作过程。老板、客户以及你自己都一定会感谢自己这么做了!同时,这会让你看起来更专业!

9.将数据保存为CSV或Pickle

毕竟我们聊的是数据科学,因此让我们再回到”数据“层面来看看。就像函数和for循环一样,CSV和Pickle文件是常用的,但它们实际上并不是最佳选择。CSV不包含架构,因此每个人都必须再次解析数字和日期。Pickles虽然解决了这个问题但只能在Python中使用并且没办法被压缩。两者都不是存储大型数据集的好地方。

1  def process_data(data,parameter):
2    data = do_stuff(data)
3    data.to_pickle('data.pkl')
4  data = pd.read_csv('data.csv')
5  process_data(data)6df_train = pd.read_pickle(df_train)

解决方案:使用parquet或其他二进制数据格式,理论上是可以进行数据压缩的。d6tflow自动将任务的数据输出保存为parquet格式,因此您无需再对它进行处理。

10.使用Jupyter Notebooks

这里有一个富有争议的论点:Jupyter Notebooks和CSV一样普遍,有很多人都在使用它们。但这其实并不能证明他们是好用的。Jupyter Notebooks让很多人都养成了上面所提到的不一些良编程习惯,特别是:

  • 您很想将所有文件转储到一个目录中

  • 您编写的代码是按照top-bottom模式运行,而不是有向无环图(DAG)模式

  • 您没有模块化您的代码

  • 不易调试

  • 代码和输出结果混在同一个文件中

  • 缺乏很好的版本控制

  • 很容易上手,但缺乏较好的扩展性

解决方案: 使用 pycharm/spyder.

posted @ 2019-04-28 10:23  京东科技开发者  阅读(246)  评论(0编辑  收藏  举报