【呆鸟译Py】Stack Overflow 大咖告诉你数据分析师的10大编程陋习

Stack Overflow 专家告诉你数据分析师的10大编程陋习

原文作者:Norman Niemer
原文链接:Top 10 Coding Mistakes Made by Data Scientists

数据分析师是“比软件工程师更懂统计学,比统计学家更懂软件工程的人”。大部分数据分析师都有统计学背景,但软件工程的经验相对会比较少。我本人是一名高级数据科学家,曾与很多初级数据分析师共事过,同时,我也是 Stack Overflow 里 Python 版块的积极分子,活跃排名在前 1%,下面是我多年经验总结出来的,初级数据分析师最常见的 10 大陋习。

1. 不分享代码里引用的数据

数据分析需要编程与数据。对于想重现开发结果的人来说,他们需要访问数据文件。这说起来只是基础知识,但很多初级数据分析师都会忘记分享代码里引用的数据文件。

import pandas as pd
df1 = pd.read_csv('file-i-dont-have.csv') # 这里会出错
do_stuff(df)

解决方案:把数据文件上传到网盘,或者把数据保存至数据库,供读者提取,但不要把文件放到 git 上,原因见下文。

2. 直接写绝对路径,无法访问

与第 1 个错误类似,代码里的路径是绝对路径,无法访问。运行你的代码时,如果需要在很多地方修改路径,这就太麻烦了。

import pandas as pd
df = pd.read_csv('/path/i-dont/have/data.csv') # 这里会出错
do_stuff(df)

# 或
impor os
os.chdir('c:\\Users\\yourname\\desktop\\python') # 这里会出错

解决方案:使用相对路径,或用全局变量设置路径。

3. 把数据与代码放在一起

数据分析代码需要数据,凭什么不能把数据与代码放在同一个目录里?那是不是还可以把图片、报告或其它垃圾文件都放在一起,呕!真是一团糟~

├── data.csv
├── ingest.py
├── other-data.csv
├── output.png
├── report.html
└── run.py

解决方案:把文件分门别类放在不同目录里,比如,data、reports、code、images 等。

4. Git Commit 时用源代码提交数据

现在大家都习惯用版本控制工具提交代码,不过用版本控制工具分享数据就没那么么合适了。分享的数据文件比较小还好说,但 Git 并没有为数据,尤其是对大型数据文件做过优化。

git add data.csv

解决方案:把大型数据文件存在网盘里。

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'])

解决方案:不要写成线性的链式函数,数据分析代码最好是完成各种任务的依赖项这种形式,建议了解下 airflow

6. 写循环

与函数一样,For 循环也是数据分析师的编程必修课,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]
# 应该用: scipy.stats.zscore(x)

# 或

groupavg = []

for i in df['g'].unique():
    dfg = df[df['g'] == i]
    groupavg.append(dfg['g'].mean())
# 应该用: df.groupby('g').mean()

解决方案Numpyscipypandas 提供了多种可以替代循环的向量化函数。

7. 不写单元测试

数据、参数、用户输入的变化都会导致代码崩溃,很多时候,出了问题你都注意不到。输出结果有问题,以此做出的决策同样也会有问题,请记住,有问题的数据只会导致有问题的决策!

assert df['id'].unique().shape[0] == len(ids) # 所有数据是否都 id?
assert df.isna().sum()<0.9 # 捕获缺失值
assert df.groupby(['g','date']).size().max() ==1 # 是否有重复值或日期?
assert d6tjoin.utils.PreJoin([df1,df2],['id','date']).is_all_matched() # 所有 id 都匹配吗?

解决方案:使用 assert 语句检查数据质量。 pandas 有质量检测的功能,数据分析师可以尝试一下。

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

我们再把目光转回到数据,毕竟我要讲的是数据分析。与前面说过的循环与函数一样,CSV 与 Pickle 文件是数据分析师最喜欢的文件格式,但其实这两种格式都没那么好。CSV 不支持模式(Schema),导入数据后还要重新解析数字与日期。Pickle 文件解决了这个问题,但只能用于 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 或其它带数据模式(Schema)的二进制格式,最好是能压缩数据的格式。

10. 依赖 Jupyter Notebook

这一点争议很大:Jupyter Notebook 与 CSV 一样都是数据分析师的最爱,但这并不代表它们就非常好了。实际上,Jupyter Notebook 是上面提及的很多软件工程陋习的源泉,具体如下:

  1. 把所有文件都堆在一个文件夹里;
  2. 不用 DAG,而是编写由上向下的线性运行代码;
  3. 不利于模块化编程;
  4. 很难调试(debug)代码;
  5. 代码与输出结果都混在一个文件里;
  6. 版本控制不好。

总之,Jupyter Notebook 上手容易,深入难。

解决方案:使用 IDE,如,pycharmspyderVSCode


文章到这里看似结束,但其实并没有结束,作者在原文里要表述的也不止这些,更多的还是想推广 Databolt 推出的 python 数据科学支持库, d6t-python。该支持库包括了几个组件,d6tflowd6tpiped6tstackd6tjoin 。说明如下:

  • d6tflow,与 airflow 类似,用于控制数据分析工作的工作流,解决文中第 5、9 中的问题。

  • d6tpipe,创建公开或私有的远程文件存储,推送或取回数据文件,与他人共享数据文件,还可以管理多个项目的数据文件,解决文中第 1、2、4 中的问题。

  • d6tstack,用于提取数据,支持 xls、csv、txt 等源文件,可以输出为 csv、Parquet、SQL 与 pandas 格式的数据,提高了数据文件读取写入的性能,还可以检查与修复数据文件中的模式(Schema)问题。

  • d6tjoin,无需自己编写代码即可轻松 join 数据集,为字符串、日期与数字提供最佳匹配。比如,无需手动处理即可匹配相似但不相同的地址、姓名、日期。

d6t-python

呆鸟云:原文虽然有软广的嫌疑,但在很多方面也刺痛了呆鸟这颗数据分析老白的心,所以在正文里剔除了软广的内容,让大家可以专心阅读。

结尾加上了 d6t-Python 的介绍是因为虽然自己没用过,但这个支持库看起来也挺美,有兴趣的朋友可以亲手一试,也许会有惊喜哦。


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,142评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,298评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,068评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,081评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,099评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,071评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,990评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,832评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,274评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,488评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,649评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,378评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,979评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,625评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,643评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,545评论 2 352