初于2019年4月26日发布在https://hackersandslackers.com。
轻松的Dataframe清理技术,范围从删除有问题的行到选择重要的列。
< class="pgc-img">>成为一名数据工程师会使事情变得无法清晰表达。 似乎不可避免的是,每个善意的Spark教程都注定会在没有太多解释的情况下陷入难以理解的代码墙。 这在StackOverflow中甚至显而易见,在这里,简单的问题经常会被荒谬的不必要的解决方案所满足(停止为所有内容制作UDF!)无论如何,我要说的是,点击这些内容需要很多勇气,在这里您 是。 我感激你。
在上一集中,我们介绍了一些Spark基础知识,与Databricks一起使用,并开始将数据加载到Dataframes中。 现在,我们通过接触每个数据爱好者最喜欢的主题:清理数据,来更深入地研究Dataframes。 为了使它有趣,我选择了我能找到的最肮脏的数据集:FDA药物执行!
排行
我们不必长时间查看这些数据就可以发现一些漏洞:
< class="pgc-img">>查看所有这些空单元格。 耻辱。 让我们来应对这些麻烦制造者。
删除具有空值的行
如果您是Pandas的粉丝,您可能会想"这是.dropna()的工作!"事实证明,您的定位可能比您想像的要多-PySpark Dataframes也提供了一种删除NA的方法 / A值,它恰好被称为.dropna()!
df=df.dropna()
display(df)
关键字参数将使您有宾至如归的感觉:
· 方法:接受"任何"或"全部"。 如果为" any",则包含所有空值的行将被完全删除(默认)。 如果为"全部",则仅删除完全为空的行。
· thresh:接受表示"阈值"的整数,表示行必须删除之前必须有多少个空单元格。 Tresh是how=any和how=all之间的中间地带。 结果,脱粒的存在将覆盖如何脱粒。
· 子集:接受列名称列表。 存在子集时,将仅根据提供名称的列检查N / A值。
PySpark没有就位的概念,因此,仅当我们将Dataframe设置为等于受影响Dataframe的值(df=df.dropna())时,才会应用针对Dataframe运行的任何方法。
我的数据集太脏了,以至于运行dropna()实际上删除了所有500行! 是的,实际上每行中都有一个空单元格。 这是我们将从列名传递到子集的好处:
df=df.dropna(subset=['postal_code', 'city', 'country', 'address_1'])
display(df)
事情看起来已经很干净了:
< class="pgc-img">>替换N / A值
尽管N / A值可能会损害我们的分析,但有时完全放弃这些行甚至会带来更多问题。 考虑一下我们想获得汇总数据的情况:通过从总池中删除记录并删除本应计数的记录,删除整行将很容易歪曲汇总统计信息。 在这些情况下,fillna()可以为您提供帮助。
fillna()接受一个值,并将用该值替换找到的所有空单元格,而不是删除行:
df=df.fillna(0)
display(df)
fillna()还接受可选的子集参数,就像dropna()一样。
删除重复的行
清理数据的前十大方法是dropduplicates()方法。 就其本身而言,在Dataframe上调用dropduplicates()会删除行,其中一行中的所有值都被另一行重复。 与到目前为止我们介绍的其他两种方法一样,dropduplicates()也接受subset参数:
df=df.dropduplicates(subset="recall_number")display(df)
从数据框选择数据
还有一个问题:它有很多无用的列。 不,认真地,检查一下运行df.printSchema()时会发生什么:
root
|-- classification: string (nullable=true)
|-- center_classification_date: timestamp (nullable=true)
|-- report_date: timestamp (nullable=true)
|-- postal_code: string (nullable=true)
|-- termination_date: timestamp (nullable=true)
|-- recall_initiation_date: timestamp (nullable=true)
|-- recall_number: string (nullable=true)
|-- city: string (nullable=true)
|-- more_code_info: string (nullable=true)
|-- event_id: integer (nullable=true)
|-- distribution_pattern: string (nullable=true)
|-- openfda_application_number: string (nullable=true)
|-- openfda_brand_name: string (nullable=true)
|-- openfda_dosage_form: string (nullable=true)
|-- openfda_generic_name: string (nullable=true)
|-- openfda_manufacturer_name: string (nullable=true)
|-- openfda_product_ndc: string (nullable=true)
|-- openfda_product_type: string (nullable=true)
|-- openfda_route: string (nullable=true)
|-- openfda_substance_name: string (nullable=true)
|-- openfda_spl_id: string (nullable=true)
|-- openfda_spl_set_id: string (nullable=true)
|-- openfda_pharm_class_moa: string (nullable=true)
|-- openfda_pharm_class_cs: string (nullable=true)
|-- openfda_pharm_class_pe: string (nullable=true)
|-- openfda_pharm_class_epc: string (nullable=true)
|-- openfda_upc: string (nullable=true)
|-- openfda_unii: string (nullable=true)
|-- openfda_rxcui: string (nullable=true)
|-- recalling_firm: string (nullable=true)
|-- voluntary_mandated: string (nullable=true)
|-- state: string (nullable=true)
|-- reason_for_recall: string (nullable=true)
|-- initial_firm_notification: string (nullable=true)
|-- status: string (nullable=true)
|-- product_type: string (nullable=true)
|-- country: string (nullable=true)
|-- product_description: string (nullable=true)
|-- code_info: string (nullable=true)
|-- address_1: string (nullable=true)
|-- address_2: string (nullable=true)
|-- product_quantity: string (nullable=true)
我什至不知道其中的一些专栏。 即使我删除了我不认识的每一列,我仍然会浪费大量时间在此列表上。 幸运的是,我们有select()。 当我们在Dataframe上调用select()时,我们可以显式地调出要保留的列:
df=df.select('classification', 'report_date', 'termination_date', 'city', 'distribution_pattern', 'status', 'product_type', 'country', 'product_description', 'address_1', 'address_2', 'product_quantity')
display(df)
我们的数据开始看起来可以被人类消化(不同于表中所列的可能可怕的药物):
< class="pgc-img">>筛选资料
有时,我们将处理包含许多异常值的数据,这些异常值会扭曲我们的结果。 有时候,我们只希望处理属于特定信息子集的行。 我们将按照以下方式清理数据,使其仅包含发生在南旧金山的案件:
df=df.filter(df.city=="South San Francisco")
filter()的内容将始终是一个条件,在此条件下,我们会将特定列中的值与预期值进行比较。 访问Dataframe列的最简单方法是使用df.column_name语法。
在本例中,我们正在将包含字符串的列与提供的字符串South San Francisco进行比较(对于数值,我们也可以使用大于和小于运算符)。
按字符串值过滤
除了通过完美匹配进行过滤之外,还有许多其他强大的方法可以在PySpark中通过字符串进行过滤。 看一看:
· df.filter(df.city.contains('San Francisco'):返回其中列的字符串包含提供的子字符串的行,在我们的示例中,按包含子字符串" San Francisco"的行进行过滤将是一种很好的方法 旧金山的所有行,而不仅仅是"南旧金山"。
· df.filter(df.city.startswith('San')):返回其中字符串以提供的子字符串开头的行。
· df.filter(df.city.endswith('ice')):返回其中字符串以提供的子字符串开头的行。
· df.filter(df.city.isNull()):返回其中提供的列中的值为空的行。
· df.filter(df.city.isNotNull()):与上述相反。
· df.filter(df.city.like('San%')):执行包含LIKE子句的类似SQL的查询。
· df.filter(df.city.rlike('[A-Z] * ice $')):执行一个正则表达式过滤器。
· df.filter(df.city.isin('San Francisco','Los Angeles')):查找行,其中列的字符串值与提供的任何字符串完全匹配。
除了按字符串过滤外,我们还可以按将值存储为日期或日期时间的列进行过滤。 也许最有用的日期过滤方法是使用between()方法,它使我们能够在特定日期范围内查找结果。 在这里,我们找到了2013年和2014年报告的所有结果:
df=df.filter(df.report_date.between('2013-01-01 00:00:00','2015-01-11 00:00:00'))
通过where()过滤
.where()是达到与filter()相同效果的另一种方式:
df=df.where((df.city=="South San Francisco"))
排序我们的数据框
最后,有几种方法可以根据喜好对Dataframe中的数据进行排序。 我的首选方法是使用orderBy():
df=df.orderBy('report_date', ascending=False)
orderBy()以我们期望的方式对结果进行排序:字符串列按字母顺序排序,数字列按时间顺序排序,依此类推。ascending关键字参数允许我们在升序等于False时显示这些结果的降序。
请注意,我们是如何将" report_date"作为字符串传递的,而不是df.report_date? PySpark出于某些原因允许我们执行此操作。 但是,这在过滤时将不起作用,因为df=df.filter(" city"==" South San Francisco")似乎我们正在尝试根据字符串评估字符串。
获得相同效果的更糟糕的方法是使用sort()方法。 sort()比orderBy()更糟糕,因为语法更丑陋,并且因为它要求我们导入一些东西才以降序列出结果:
from pyspark.sql.functions
import desc
df=df.sort(desc("published_at"))
那就是我们今天所有的时间。 下次当我们探索在PySpark中转换Dataframes的神奇世界时,请加入我们。
(本文翻译自Todd Birchard的文章《Cleaning PySpark Dataframes》,参考:https://hackingandslacking.com/cleaning-pyspark-dataframes-1a3f5fdcedd1)
果问你
家里最脏的地方是哪里?
很多人第一反应是:厕所、马桶!
然而实际上
我们每天都在用的冰箱、洗衣机……
长年累月地使用下来
内部如果不及时清洁
可能比马桶还脏!
冰箱有“冷藏冷冻”大法护体,被很多人当成食物的“保险箱”,什么都往里塞。
殊不知,冰箱暗地里或许早已叛变,和致病菌“同流合污”了。
看看这是不是你家的冰箱?
国外一项针对200台家用冰箱的调查发现:
冰箱架子、蔬菜框和用于擦拭冰箱的抹布等物体上,微生物污染较为严重。
其中59.5%的冰箱检测出了单增李斯特菌,32.5%的冰箱检测出了沙门氏菌[1]。
国内也有研究发现,家用冰箱冷藏室微生物污染严重,检测出葡萄球菌、大肠杆菌等多种微生物[2],就算是冷冻室,也不能“冻死”细菌。
如果吃了这些被致病菌污染的食物,轻则可能腹痛、恶心、反胃,重则上吐下泻,甚至威胁生命。
(图源:华声在线)
(图源:浙江新闻)
冰箱“藏污”重灾区:
1.冷藏室玻璃隔层
2.冷冻室抽屉
3.冷藏室排水口
4.冰箱门密封条
平时定期清洁、消毒非常重要,建议1个月进行一次彻底清洁。
冰箱清洁方式:
1.彻底清洁前,把食物全部取出后断电。
2.用干净的抹布蘸洗洁精水或者医用酒精,全方位擦拭玻璃隔层和冷藏室的内壁,再用干净的湿抹布清洁一遍后晾干(这一步很简单)。
3.冷冻室抽屉需要把食物清理出来后,用洗洁精仔细清洗,再用清水冲洗干净后晾干(注意抽屉安装顺序,别搞混了)。
4.排水口是冷藏室内壁上的一个小孔,用一根小棍子捅进去疏通即可。
5.冰箱门密封条是很多人都会忽视的一个地方,清洁时可以用餐叉裹住纸巾或者抹布后,用医用酒精蘸湿,沿着密封条内部进行擦拭。
还记得,家里的饮水机工作多久了吗?关心过它脏不脏吗?
(图源:央视新闻)
有研究表明,饮水机的内胆、聪明座(桶与机体之间的连接构件)等部位,长期不清洗消毒,容易滋生大量的微生物,污染饮用水[9]。
(图源:广东卫视)
另外,在换水过程中,如果没洗手,也容易污染桶口、聪明座等部位。长期不清洁还容易形成水垢……
这种饮水机本身就不卫生,再加上一桶水喝个十天八天,培养了很多细菌、病毒,病从口入不是没有道理的呀!
(图源:soogif)
接下来重点来了,怎么清洗饮水机?
1.针对机身,用医用酒精蘸湿干净的抹布,清洁出水口、接水槽和饮水机外壳。
(图源:《生活大调查》节目)
2.针对聪明座,可以取下来,用干净的湿抹布沾湿医用酒精进行清洁和消毒。
(打开聪明座示意图。图源:广东卫视)
3.针对内胆,将专用的饮水机消毒剂根据说明书按比例稀释后倒入内胆,并静置20分钟左右(不同的消毒剂可能存在差别),然后打开饮水机所有排水口,将水排出后,用清水从聪明座中持续冲洗饮水机内胆,直到没有消毒剂的气味为止。
(饮水机内胆示意图。图源:广东卫视)
(打开饮水机排水口示意图。图源:腾讯视频-by比克大魔王)
洗衣机天天帮人们洗衣服,应该很干净吧?但是你见过洗衣机拆开后的样子吗?
(图源:网络)
呕~~~容我先吐一会儿!马桶都比这干净呀!
上海市疾病预防控制中心曾对家用洗衣机的污染情况进行调查,结果显示:
洗衣机的细菌总数超标率为81.3%,总大肠菌群检出率为100%,霉菌检出率超过60.2%[4]。
如果用这样的洗衣机,洗不干净不说,还容易让衣服受到二次污染。穿了这样被污染的衣物,易引发皮肤瘙痒、红疹等皮肤疾病,甚至导致妇科疾病[3]。
那怎么正确清洁洗衣机呢?
洗衣机清洁方式:
1.日常清洁:洗衣机用完后开盖通风、擦净内桶、封口密封圈,清理过滤网袋,能一定程度上减少洗衣机的污染[4]。另外,具有自清洁功能或者带抗菌功能的洗衣机,要确保自清洁功能正常(多数需要按照说明书添加清洁剂)。
(图源:网络)
2.定期彻底清洁:定期使用专用的、具有抗菌去污功能的洗衣机清洁剂对洗衣机进行清洁,其优点是不需要对洗衣机进行拆卸即可操作[5-6]。
3.另外,建议视使用情况定期进行拆解清洁。如果动手能力强,可以自行拆解洗衣机,将洗衣槽、内桶壁上附着的污垢清理干净;考虑到用电安全,最好请专业的家电清洁人士上门拆洗,毕竟健康无价~
(图源:网络)
(图源:soogif)
很多空调表面看着光鲜亮丽,实际上内里已经成这样了……↓↓↓
这样的空调用起来,只能说一句:细菌来得太快,就像龙卷风……
有研究显示,空调是室内尘螨的重要来源,而这些尘螨是引发过敏性疾病的重要诱因之一[7]。
儿童的抵抗力相对成人较差。夏季空调使用时间超过8小时/天,是导致儿童患哮喘、支气管炎、肺炎、过敏性鼻炎的重要诱因[8]。
所以,就算是为了祖国的花朵,也一定要定期清洗空调啊!!
空调(室内机)清洁方式:
1.自行清洁空调时,先断电,然后用干净的湿抹布清洗空调外壳。如果空调位置较高,擦的时候注意安全。
(图源:网络)
2.打开空调外壳,取出过滤网(没错,就是上图中最脏的那层网格),用刷子轻刷,然后慢慢清洗干净。
(图源:网络)
3.过滤网晾干后安装回去,盖好空调外壳。
(图源:网络)
一般人能做到清洗过滤网这一步已经很厉害了!这样的清洁可以3个月左右进行一次。
如果觉得麻烦,可以半年左右,请专业清洁人士上门彻底清洗一次。
看完是不是吓一跳?
这些每天都在用的电器
记得定期对它们进行深度清洁
没(懒)经(得)验(洗)的话
也可以直接请专业人士上门清洁
友情提示,千万要注意用电安全
收藏本文,不会操作的时候打开看看吧~
姑娘问:
要把大象装冰箱,
总共分几步?
???
过节真是太可怕了!二姑娘还没从春节的阴影里走出来,元宵节都已经过去了。
只要逢年过节,老爸老妈都会囤上各种鸡鸭鱼肉、蔬菜水果...现在又多了无数的汤圆。
冰箱当然怎么塞都不够用。即便是市面上的冰箱越做越大,或者家里常备两个冰箱,也没有什么卵用,东西还是没有地方塞。
讲真,现如今买新鲜的蔬果鲜肉其实很方便的,完全用不着这么一下子囤这么多啊,每天活在菜还没吃完就坏掉了的焦虑里,还是很炸裂的。
更别说,冰箱里的细菌多到炸裂,有研究称家里最脏的地方就是冰箱,而且有46%家庭的冰箱都无法通过细菌检测。
但是如果你真的一不小心买多了,也别担心,二姑娘教你如何把大象放冰箱...哈哈哈,开玩笑,如何把更多的食材放冰箱,同时还能保持干净卫生。
?
首先回想一下,自己在什么情境下会有把冰箱砸了的冲动?
是一打开就扑面而来的异味;
是所有东西都油腻腻的,无从下手;
是乱七八糟的堆叠再塞不进任何东西;
是突然发现不知道什么时候买的菜,已经烂掉了...
这些情况或多或少你都会遇到一些吧,反正二姑娘是遇到过的。
小小的冰箱收纳起来可是大有诀窍的,对应起上面的惨烈情况,二姑娘带大家完成三个小目标。
没有异味
易拿取,易归位
看起来整洁干净
对对对,明眼的你是不是也发现了,三个小目标是相辅相成的。
【1】
杜绝异味
从源头开始
说起冰箱,怎么能不谈异味呢?
网上随便搜搜就有无数的去除异味小妙招...
上学的时候,老师说要防患于未然。
冰箱本来空间就小,又密闭,异味问题,只靠后期去除又怎么能行,必须要从源头解决,防患于未然。
有人肯定要说了,我哪知道源头是什么啊?
别着急嘛!二姑娘这里有方法啊,虽笨,但是最靠谱。就是,把所有食物密封存放,不让味道散发出来,更不会有气味“交叉感染”。
喂喂喂,先别笑。密封食物也是有讲究的,不信,二姑娘先举几个例子。
人人都知道,鱼是异味界的扛把子,经常一条鱼毁了一冰箱的菜。那是因为你没有像二姑娘这样处理。
把碍事的鱼尾巴先剪掉
用烘焙纸紧紧地裹住鱼
再用锡纸裹上一层
任你是海里的还是江里河里的
保准断了与外界的气味联络
其实牛羊猪肉跟鱼啊海鲜的气味差不离,因此处理起来也花费了点心思。
准备好密封的保鲜盒,玻璃材质的最佳。四周裹上烘焙纸,把肉按份叠放,一份上叠一层烘焙纸,取用的时候,一份是一份,干净卫生。
异味界的扛把子解决了,其他都是小意思。绝对都逃不出厨房纸、保鲜袋和保鲜盒的手掌心。
比如原本一大锅的高汤,只能塞在空间最大的位置,又占地方,还不能保证味道不散发出来。
但如果,用到二姑娘说的密封法...可以先把高汤冻在冰格里,成型后统一存放在保鲜盒中,冰的体积小不说,还更卫生。
除了高汤,还有柠檬汁也可以这样来保鲜。想喝的时候,取一块丢在杯子里,加冰的柠檬水很快就能喝到。是不是很妙啊。
嫌保鲜盒贵的可以考虑保鲜袋,最好是带塑封条的那种。当然买不到带塑封条的,也可以用保鲜袋+长尾夹的组合来密封。
长尾夹上贴上标签,袋子里有什么一目了然。
“能做到这一步,冰箱要是还能有异味,算我输。”
二姑娘曾经在小花面前夸下海口,随后便被啪啪啪打脸了。
小花家的冰箱在二姑娘帮忙收拾完的第三天,又有异味了。啊...实在是因为忽略了小花的邋遢和懒惰。
二姑娘说,所有东西都密封。
好,都密封了。
二姑娘没说,所有东西用完要把容器外残留的汤汁酱料擦拭干净。
好,瓶子上乌漆麻黑的,黏黏腻腻的就直接放到冰箱里去了。
哎,心好累,觉得自己太像个老妈子了。那干脆再啰嗦几句吧。
除了密封好以外,所有放进冰箱的东西都要保证外表干净,不粘腻。冰箱里有残留的汤汁污垢,一定要在第一时间擦拭干净。
看上去很干净的冰箱,也要定时定期彻底清洁。角角落落,边边框框都不能拉下。尤其是冰箱的密封条,是细菌滋生的重要场所,一定要仔细清理。
【2】
易拿取,易归位
顺手原则
跟习惯挂钩
当所有东西都被装进差不多的容器里,我们可以考虑的也就更多。
怎样才能又快又准地拿到我们想要的东西?!
按照小花的身高一米六来算,她家的冰箱至少有一米八高,于是冰箱里必然有些角落会被她无视和遗忘~
没办法,身高有限的情况下,更要合理布局。
冷藏层
首先按照小花身高,将冷藏区分为A、B、C三个区域。
A区在上层,属于小花的盲区,也是容易被小花遗忘的角落。二姑娘建议放置保质期长,不常用的食物,比如酱菜、调味品。这样即使偶尔忘了,食材也不会立马腐坏。
B区属于视线等高层,就是打开冰箱不费力就能看到的区域,绝不会被遗忘的角落。很适合放希望马上吃完的食物,或者保质期短暂的,必然能达到提醒自己赶快吃掉它们的作用。
C区是保鲜区,是收纳抽屉的形式。这里的温度要比上面两处的低,放近期要食用的肉类食材最合适了,保鲜的同时可以慢慢消冰。
看上去很简单,但也不是一股脑全部塞进去就可以了。
在ABC的基础上,还可以有A左A右,B左B右,C左C右。剩菜剩饭在左,那新鲜的食材一定在右,互不打扰。
冰箱分层不合理的,也可以借助工具。咱们自己分层把空间合理规划了。
冷藏层还有一个重要的组成部分——冰箱门。
往往也是苦力劳动者,什么饮料,番茄酱,花生酱,牛奶,鸡蛋,全部都能塞在窄窄的冰箱门上。
但是拜托拜托,为了冰箱的寿命,请大家善待冰箱门好吗?
冰箱门守则一:又重又高的物品,要靠着冰箱门的轴承放。(就是下图中红框框的部分。)
冰箱门守则二:尽可能统一包装瓶。整齐统一,收拾起来也方便。
冰箱门守则三:使用收纳盒,收纳不规则的瓶瓶罐罐。一眼就能看到自己想要的酱料在哪里。
蔬果保鲜层
到了这里的蔬果区,肯定有不少人说,蔬菜也需要收纳啊?
当然啦,蔬果区可是最大意不得的区域。想想看,是不是清理冰箱的时候总能看到不少发霉叶子黄掉的蔬菜,根本想不起来是什么时候买来的。
但如果你借用收纳盒,让蔬菜站起来,就不会出现人挤人(呸,划掉)菜压菜的现象了。
蔬菜是站着还是躺着,还得由本身的形状来确定。
零零散散的蔬菜现象绝不能出现在这里。
胖的就躺着,瘦的一定是站着。青菜也算是竖条瘦长的,也得站着。
冷冻区
冷冻区一般都位于冰箱最底端,要弯腰拿取。
那食物竖直放置,再在顶部标记上名称、赏味期限。最合理的一目了然目标就达到了。
冷冻里的鱼、肉类,还是速冻食品,是收纳袋,还是储物盒,竖直收纳才是王道,省空间还整齐好看。
对了,刚学会鱼的包裹大法是不是可以现学现用了...
【3】
看上去
方便整洁
最开始,二姑娘就提到,今天的三个小目标是相辅相成的。
按照二姑娘的方法做到无异味,然后按习惯易拿取,易放回,那最后的方便整洁是必然的结果。
不信你看这些美图,不管东西是多是少,是不是都符合了二姑娘的收纳原则。
密封罐做到无异味
上层收纳米面
中层是马上要吃的食材
细致如日本主妇
也脱离不开这些规律
不过只有更细致的划分
没有最细致
看到这里,你是不是要撸起袖子大干一场了?
别急,还有一点可千万别忘了...先把电源拔掉,节约用电!
二姑娘家的狗很乖
扫一扫 不会咬人
?
跟二姑娘说说
你家冰箱什么样?
是“重灾区”吗?