使用pandas遇到的一些坑及解决方案(1)


最近在频繁的使用pandas处理数据问题,所以把遇到的问题慢慢整理一下,给自己个交代,另外如果有处理方法可以优化的地方,也希望小伙伴们可以指出来,谢谢。

nan值定位的正确方法

df.isnull()真没啥用

  • df.isnull()这个命令,是将数据集的nan值显示为1,不为nan值的显示为0

  • 说实话,df.isnull() 在我看来没什么用,对于一个海量数据来讲,一眼根本就看不出来哪里是 nan值,哪里不是nan值,当然你要专门统计个数的话,可以使用,举个例子来看

import pandas as pd
df1 = pd.DataFrame({"name": ["小王", "小红", "小芳", "小明"], "age": [18, 19, 20, 22], "sex": ["男", "女", "女", "男"]})
df2 = pd.DataFrame({"name": ["小王", "小红", "小芳", "小绿"], "score": [100, 98, 95, 60], "sex": ["男", "女", "女", "男"]})

# 这里为举例子的全面性,使用左连接生成一个df,suffixes=["_old", "_new"]我个人偏向于这种写法,因为左连接,一般是将右表的内容更新给左表,那么用old和new一眼就可以看出哪个是要被替换的数据
df = pd.merge(df1, df2, on=["name"], suffixes=["_old", "_new"], how="left")
print(df)
  • 拼接完的原表长这个样子
    tIaHmD.png
  1. 命令:df.isnull()
  2. 这个命令数据呈现如下图所示,这还是数据比较少的情况下,数字1的位置为nan值,看得出来,如果是海量数据,但是数据集中可能只有极个别行存在nan值,那么用这个命令根本没有意义,这时另一个命令就显得非常有用:df[df.isnull().values==True]
    tIdZpq.png

df[df.isnull().values==True] 很舒服

  • 命令:df[df.isnull().values==True]

  • 这个命令数据呈现如下图所示,(按理说应该只有一条记录,但是这里出现两条,但是无伤大雅,明显能看出来这是同一条记录,因为index相同,这个为什么这样我后面再研究下,对我要说的结论没有影响),很清晰的把数据集所有行中出现nan的原数据显示给你
    tIwxL8.png

  • df[df.score.isnull().values==True]

  • 当然,如果你不关心所有的出现nan的数据,只关心拼接后的某一列是否有nan值的出现,那么这个命令同样非常友好:df[df.列名.isnull().values==True]

  • 例如我只关心两个表拼接后,有没有同学没有成绩呢,那么就要看score这个列有没有nan值就可以了,结果如下图所示,很准确的定位到你所需要查看的数据

tIBZ9A.png

日期加减问题的正确写法

这个主要涉及到datetime中日期的加减,遇到了坑,需求如下:需要将日期数据列(date类型)和整形数字列(int类型)相加,计算新的日期,详见下方代码,代码下方是例子

import datetime
#########################        错误的写法			#########################

# 一般人可能第一印象就如同我如下的写法一样,但是series不支持
# 假设数据如下, ord_dt为订货时间, days为送货天数, 现在要将订货时间+送货时间算出到货时间
df = pd.DataFrame({"name": ["小明", "小红", "小李"], "ord_dt": ["2020-05-01", "2020-05-01", "2020-05-01"], "days": [10, 3, 4]})
df["ord_dt"] = pd.to_datetime(df["ord_dt"])
df["arr_dt"] = df["ord_dt"] + datetime.timedelta(days=df["days"])
print(df)

# 程序报错,信息如下
Traceback (most recent call last):
  File "/home/chen/pycharm-folder/pycharm-2019.3.3/plugins/python/helpers/pydev/pydevd.py", line 1434, in _exec
    pydev_imports.execfile(file, globals, locals)  # execute the script
  File "/home/chen/pycharm-folder/pycharm-2019.3.3/plugins/python/helpers/pydev/_pydev_imps/_pydev_execfile.py", line 18, in execfile
    exec(compile(contents+"\n", file, 'exec'), glob, loc)
  File "/home/chen/PycharmProjects/requests_check/main.py", line 13, in <module>
    df["arr_dt"] = df["ord_dt"] + datetime.timedelta(days=df["days"])
TypeError: unsupported type for timedelta days component: Series
#########################        错误的写法			#########################


#########################        正确的写法			#########################

import datetime
# 假设数据如下, ord_dt为订货时间, days为送货天数, 现在要将订货时间+送货时间算出到货时间
df = pd.DataFrame({"name": ["小明", "小红", "小李"], "ord_dt": ["2020-05-01", "2020-05-01", "2020-05-01"], "days": [10, 3, 4]})

# 这里的转化日期写法是为了不要时分秒,我目前摸索出来的方法只有这个可以只显示到日期,但是效率不高
df["ord_dt"] = df["ord_dt"].apply(lambda x: pd.to_datetime(x).date())

# 用lambda函数的方式进行日期的加减就可以了
df["arrdt"] = df.apply(lambda x: x.ord_dt + datetime.timedelta(days=x.days), axis=1)
print(df)

#########################        正确的写法			#########################

初始数据集
tIrz1s.png
计算之后的数据集,到货时间分别为2020-05-11···
tIsKnx.png

分组聚合不改变列名生成新表

**分组聚合(df.groupby())**是pandas中比较常用的命令,有几个点我还是强调一下

  1. df.groupby() 命令要想显示数据集,那么一定要加聚合的条件,比如sum(), count()等等,比如
# 需求为,程序要统计男生和女生数量

# ##########################	不加聚合条件的程序和结果	##########################

df = pd.DataFrame({"name": ["小王", "小红", "小芳", "小绿"], "score": [100, 98, 95, 60], "sex": ["男", "女", "女", "男"]})
# 如果不加聚合条件
df = df.groupby(["sex"])
print(df)

df = <pandas.core.groupby.generic.DataFrameGroupBy object at 0x7f615eb2ff50>
# ##########################	不加聚合条件的程序和结果	##########################


# ##########################		加聚合条件的结果		##########################
df = pd.DataFrame({"name": ["小王", "小红", "小芳", "小绿"], "score": [100, 98, 95, 60], "sex": ["男", "女", "女", "男"]})
# 增加聚合条件,则可以重新生成一张新表
df = df.groupby(["sex"]).count()
print(df)
结果如下图所示
# ##########################		加聚合条件的结果		##########################

tI6g00.png
2. 但是你会发现,你要统计的列名成了索引,这在后面的操作可能不太方便,(当时困扰了我很久,因为我后面还需要这个新生成的临时表的列名做级联更新操作),还是需要将sex作为列名显示,那么有个参数你需要加上,as_index=False

df = pd.DataFrame({"name": ["小王", "小红", "小芳", "小绿"], "score": [100, 98, 95, 60], "sex": ["男", "女", "女", "男"]})
# 增加as_index参数可以将数据按原格式返回,并生成一张新表,方便在后面用作拼接等操作
df = df.groupby(["sex"], as_index=False).count()
print(df)
# 结果如下,可以看到是以原有表列名的方式返回新的数据集

tI6q76.png

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值