IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Pandas数据处理-map、apply、applymap详解

    breezedeer发表于 2020-04-12 17:36:00
    love 0
    一盏灯, 一片昏黄; 一简书, 一杯淡茶。 守着那一份淡定, 品读属于自己的寂寞。 保持淡定, 才能欣赏到最美丽的风景! 保持淡定, 人生从此不再寂寞。

    在日常的数据处理中,经常会对一个DataFrame进行逐行、逐列和逐元素的操作,对应这些操作,Pandas中的map,apply和applymap可以解决绝大部分这样的数据处理需求。这篇文章就以案例附带图解的方式,为大家详细介绍一下这三个方法的实现原理,相信读完本文后,不论是小白还是Pandas的进阶学习者,都会对这三个方法有更深入的理解。

    boolean=[True,False] 
    gender=["男","女"] 
    color=["white","black","yellow"] 
    data=pd.DataFrame({     
        "height":np.random.randint(150,190,100),     
        "weight":np.random.randint(40,90,100),     
        "smoker":[boolean[x] for x in np.random.randint(0,2,100)],     
        "gender":[gender[x] for x in np.random.randint(0,2,100)],     
        "age":np.random.randint(15,90,100),     
        "color":[color[x] for x in np.random.randint(0,len(color),100) ] 
    } 
    )
    

    数据集如下所示,各列分别代表身高、体重、是否吸烟、性别、年龄和肤色

    Series数据处理

    如果需要把数据集中 gender 列的男替换为1,女替换为0,怎么做呢?绝对不是用for循环实现,使 用 Series.map() 可以很容易做到,少仅需一行代码。

    #①使用字典进行映射 
    data["gender"] = data["gender"].map({"男":1, "女":0}) 
    #②使用函数
    def gender_map(x):
        gender = 1 if x == "男" else 0
        return gender
    #注意这里传入的是函数名,不带括号
    data["gender"] = data["gender"].map(gender_map)



    不论是利用字典还是函数进行映射,方法都是把对应的数据逐个当作参数传入到字典或函数中,得到映射后的值。

    apply

    同时Series对象还有 apply 方法, apply 方法的作用原理和 map 方法类似,区别在于 apply 能够传入 功能更为复杂的函数。怎么理解呢?一起看看下面的例子。
    假设在数据统计的过程中,年龄 age 列有较大误差,需要对其进行调整(加上或减去一个值), 由于这个加上或减去的值未知,故在定义函数时,需要加多一个参数 bias ,此时用 map 方法是操 作不了的(传入 map 的函数只能接收一个参数), apply 方法则可以解决这个问题

    def apply_age(x,bias):
        return x+bias
    
    #以元组的方式传入额外的参数
    data["age"] = data["age"].apply(apply_age,args=(-3,))


    可以看到age列都减了3,当然,这里只是简单举了个例子,当需要进行复杂处理时,更能体现 apply 的作用。
    总而言之,对于Series而言, map 可以解决绝大多数的数据处理需求,但如果需要使用较为复杂的 函数,则需要用到 apply 方法。

    DataFrame数据处理

    apply

    对 DataFrame 而言, apply 是非常重要的数据处理方法,它可以接收各种各样的函数(Python内置 的或自定义的),处理方式很灵活,下面通过几个例子来看看 apply 的具体使用及其原理。
    在进行具体介绍之前,首先需要介绍一下 DataFrame 中 axis 的概念,在 DataFrame 对象的大多数方法 中,都会有 axis 这个参数,它控制了你指定的操作是沿着0轴还是1轴进行。 axis=0 代表操作对 列 columns 进行, axis=1 代表操作对 行row 进行,如下图所示。


    假设现在需要对 data 中的数值列分别进行取对数和求和的操作,这时可以用 apply 进行相应的操 作,因为是对列进行操作,所以需要指定 axis=0 ,使用下面的两行代码可以很轻松地解决我们的 问题。

    # 沿着0轴求和
    data[["height","weight","age"]].apply(np.sum, axis=0)
    
    # 沿着0轴取对数
    data[["height","weight","age"]].apply(np.log, axis=0)



    当沿着 轴0(axis=0) 进行操作时,会将各列( columns )默认以 Series 的形式作为参数,传入到你指定 的操作函数中,操作后合并并返回相应的结果。
    那如果在实际使用中需要按行进行操作( axis=1 ),那整个过程又是怎么实现的呢?
    在数据集中,有身高和体重的数据,所以根据这个,我们可以计算每个人的BMI指数(体检时常 用的指标,衡量人体肥胖程度和是否健康的重要标准),计算公式是: 体重指数BMI=体重/身高的平方 (国际单位kg/㎡) ,因为需要对每个样本进行操作,这里使用 axis=1 的 apply 进行操作,代码如下:

    def BMI(series):
        weight = series["weight"]
        height = series["height"]/100
        BMI = weight/height**2
        return BMI
    
    data["BMI"] = data.apply(BMI,axis=1)


    当 apply 设置了 axis=1 对行进行操作时,会默认将每一行数据以 Series 的形式(Series的索引为列 名)传入指定函数,返回相应的结果。
    总结一下对 DataFrame 的 apply 操作:

    1. 当 axis=0 时,对 每列columns 执行指定函数;当 axis=1 时,对 每行row 执行指定函数。 2. 无论 axis=0 还是 axis=1 ,其传入指定函数的默认形式均为 Series ,可以通过设置 raw=True 传入 numpy数组 。 3. 对每个Series执行结果后,会将结果整合在一起返回(若想有返回值,定义函数时需要 return 相应的值) 4. 当然, DataFrame 的 apply 和 Series 的 apply 一样,也能接收更复杂的函数,如传入参数等,实现 原理是一样的,具体用法详见官方文档。

      applymap

      applymap 的用法比较简单,会对 DataFrame 中的每个单元格执行指定函数的操作,虽然用途不如 apply 广泛,但在某些场合下还是比较有用的,如下面这个例子。

    df = pd.DataFrame(     
        {         
            "A":np.random.randn(5),         
            "B":np.random.randn(5),         
            "C":np.random.randn(5),         
            "D":np.random.randn(5),         
            "E":np.random.randn(5),     } )


    将所有的值保留两位小数显示,使用applymap

    df.applymap(lambda x:"%.2f" % x)

    引用自:

    https://www.jianshu.com/p/e76861ed1815



沪ICP备19023445号-2号
友情链接