数据科学家常犯的十大编程错误

2019年05月15日 由 sunlei 发表 741781 0


数据科学家是“比任何软件工程师都更擅长统计,比任何软件工程师都更擅长软件工程的的统计学家”。许多数据科学家都有统计学背景却缺乏在软件工程方面的经验。我是资深的数据科学家,在StackOverflow中python编码排名前1%。今天我们来聊聊我经常看到的很多(初级)数据科学家常犯的10个编程错误。

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


数据科学需要代码和数据。因此,为了让其他人能够复制你的结果,他们需要访问数据,作为最最基本的这一点,但是很多人忘记与他们的代码共享数据。
import pandas as pd

df1 = pd.read_csv('file-i-dont-have.csv') # fails

do_stuff(df)

解决方案:使用d6tpipe与代码共享数据文件或上载到s3/web/google drive等或保存到数据库,以便收件人可以检索文件(但不要将其添加到Git中,请参见下文)。

  1. 硬编码的路径


与错误1类似,如果你的硬编码路径,其他人无法访问到,那么他们不能运行您的代码,必须在很多地方查找手动更改路径。
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使您的数据易于访问。

  1. 将数据与代码混合。


既然数据科学代码需要数据,为什么不把它放在相同的目录中呢?当你在那里的时候,保存的图像,报告和其他垃圾也在那里。哎呀,真是一团糟!
├── data.csv

├── ingest.py

├── other-data.csv

├── output.png

├── report.html

└── run.py

解决方案:将目录组织成不同类别,如数据、报告、代码等。参见Cookiecutter Data Science或d6tflow项目模板并使用#1中提到的工具来存储和共享数据。

  1. Git用源代码提交数据


大多数人现在控制他们的代码的版本(如果你不这样做的话就会犯另一个错误! !见git)。为了共享数据,可能很容易将数据文件添加到版本控制中。这对于很小的数来说是可以的,但是git没有针对数据进行优化,尤其是大型文件。
git add data.csv

解决方案:使用#1中提到的工具来存储和共享数据。如果你真正想要对数据进行版本控制,请参阅d6tpipe、dvc和Git大文件存储。

  1. 编写函数而不是DAGs


关于数据的讨论已经够多了,让我们来谈谈实际的代码吧!自从你学习编码时,首先要学习的是函数,数据科学代码主要由一系列运行的线性函数组成。这就导致了一些问题。机器学习代码可能不好。
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'])

解决方案:与其使用线性链接函数,不如将数据科学代码

编写为一组任务,并在这些任务之间建立依赖关系。使用d6tflow或airflow。

  1. 循环写入


就像函数一样,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()

解决方案:Numpy、scipy和panda为你认为可能需要循环的大部分内容提供向量化的函数。

  1. 不要编写单元测试


当数据、参数或用户输入发生变化时,您的代码可能会中断,有时你根本没有注意到,这可能会导致糟糕的产出。有人根据你的输出做出决定,坏数据会导致错误的决定!

解决方案:使用assert语句检查数据质量。panda有相等测试,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?


  1. 不记录代码


我很明白你急着做分析,你急于一起把结果告诉你的客户或老板。一周后,他们

回来说“你能修改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

解决方案:即使是你交付了结果,也要多花点时间记录你所做的。你会感谢自己,其他人也会感谢你。这么做会让你更专业!

  1. 将数据保存为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或其他二进制数据格式。这在理想情况下是压缩数据的模式。d6tflowautomatically将任务的数据输出保存为parquet,所以你不需要处理它。

  1. 使用jupyter notebooks


让我们用一个有争议的结论来结束本文:jupyter notebooks作为CSV一样常见。很多人使用它们。但这不代表他们完美。jupyter notebooks助长了上面提到的很多不良的软件工程习惯,尤其是:

  • 您试图将所有文件转储到一个目录中

  • 你写的代码运行从上到下,而不是DAGs

  • 您没有模块化您的代码

  • 调试困难

  • 代码和输出混合在一个文件中

  • 他们不能很好地控制版本


开始做起来很容易,但是规模太小。

解决方案:使用pycharm或spyder。

好了,今天先聊到这里,以上就是我多年总结下来的常见的十个编程错误,希望对你们有帮助。
欢迎关注ATYUN官方公众号
商务合作及内容投稿请联系邮箱:bd@atyun.com
评论 登录
写评论取消
回复取消