美文网首页
图解Pandas的assign函数

图解Pandas的assign函数

作者: 皮皮大 | 来源:发表于2021-10-05 22:48 被阅读0次

    公众号:尤而小屋
    作者:Peter
    编辑:Peter

    大家好,我是Peter~

    本文介绍的是Pandas库中一个非常有用的函数:assign

    在我们处理数据的时候,有时需要根据某个列进行计算得到一个新列,以便后续使用,相当于是根据已知列得到新的列,这个时候assign函数非常方便。下面通过实例来说明函数的的用法。

    Pandas文章

    本文是Pandas文章连载系列的第21篇,主要分为3类:

    基础部分:1-16篇,主要是介绍Pandas中基础和常用操作,比如数据创建、检索查询、排名排序、缺失值/重复值处理等常见的数据处理操作

    进阶部分:第17篇开始讲解Pandas中的高级操作方法

    对比SQL,学习Pandas:将SQL和Pandas的操作对比起来进行学习

    image

    参数

    assign函数的参数只有一个:DataFrame.assign(**kwargs)。

    **kwargs: dict of {str: callable or Series}
    

    关于参数的几点说明:

    • 列名是关键字keywords
    • 如果列名是可调用的,那么它们将在DataFrame上计算并分配给新的列
    • 如果列名是不可调用的(例如:Series、标量scalar或者数组array),则直接进行分配

    最后,这个函数的返回值是一个新的DataFrame数据框,包含所有现有列和新生成的列

    导入库

    import pandas as pd
    import numpy as np
    
    # 模拟数据
    
    df = pd.DataFrame({
      "col1":[12, 16, 18],
      "col2":["xiaoming","peter", "mike"]})
    
    df
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: right;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>12</td>
    <td>xiaoming</td>
    </tr>
    <tr>
    <th>1</th>
    <td>16</td>
    <td>peter</td>
    </tr>
    <tr>
    <th>2</th>
    <td>18</td>
    <td>mike</td>
    </tr>
    </tbody>
    </table>

    </div>

    实例

    当值是可调用的,我们直接在数据框上进行计算:

    方式1:直接调用数据框

    # 方式1:数据框df上调用
    # 使用数据框df的col1属性,生成col3
    
    df.assign(col3=lambda x: x.col1 / 2 + 20)  
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: right;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    <th>col3</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>12</td>
    <td>xiaoming</td>
    <td>26.0</td>
    </tr>
    <tr>
    <th>1</th>
    <td>16</td>
    <td>peter</td>
    <td>28.0</td>
    </tr>
    <tr>
    <th>2</th>
    <td>18</td>
    <td>mike</td>
    <td>29.0</td>
    </tr>
    </tbody>
    </table>

    </div>

    我们可以查看原来的df,发现它是不变的

    df  # 原数据框不变的
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: right;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>12</td>
    <td>xiaoming</td>
    </tr>
    <tr>
    <th>1</th>
    <td>16</td>
    <td>peter</td>
    </tr>
    <tr>
    <th>2</th>
    <td>18</td>
    <td>mike</td>
    </tr>
    </tbody>
    </table>

    </div>

    操作字符串类型的数据:

    df.assign(col3=df["col2"].str.upper())
    
    image

    方式2:调用Series数据

    可以通过直接引用现有的Series或序列来实现相同的行为:

    # 方式2:调用现有的Series来计算
    
    df.assign(col4=df["col1"] * 3 / 4 + 25)
    
    image
    df  # 原数据不变
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: right;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>12</td>
    <td>xiaoming</td>
    </tr>
    <tr>
    <th>1</th>
    <td>16</td>
    <td>peter</td>
    </tr>
    <tr>
    <th>2</th>
    <td>18</td>
    <td>mike</td>
    </tr>
    </tbody>
    </table>

    </div>

    在Python3.6+中,我们可以在同一个赋值中创建多个列,并且其中一个列还可以依赖于同一个赋值中定义的另一列,也就是中间生成的新列可以直接使用

    df.assign(
        col5=lambda x: x["col1"] / 2 + 10,         
        col6=lambda x: x["col5"] * 5,  # 在col6计算中直接使用col5        
        col7=lambda x: x.col2.str.upper(),         
        col8=lambda x: x.col7.str.title()  # col8中使用col7
    )
    
    image
    df   # 原数据不变
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: left;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>12</td>
    <td>xiaoming</td>
    </tr>
    <tr>
    <th>1</th>
    <td>16</td>
    <td>peter</td>
    </tr>
    <tr>
    <th>2</th>
    <td>18</td>
    <td>mike</td>
    </tr>
    </tbody>
    </table>

    </div>

    如果我们重新分配的是一个现有的列,那么这个现有列的值将会被覆盖:

    df.assign(col1=df["col1"] / 2)  # col1直接被覆盖
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: left;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>6.0</td>
    <td>xiaoming</td>
    </tr>
    <tr>
    <th>1</th>
    <td>8.0</td>
    <td>peter</td>
    </tr>
    <tr>
    <th>2</th>
    <td>9.0</td>
    <td>mike</td>
    </tr>
    </tbody>
    </table>

    </div>

    对比apply函数

    我们在pandas中同样可以使用apply函数来实现

    df  # 原数据
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: left;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>12</td>
    <td>xiaoming</td>
    </tr>
    <tr>
    <th>1</th>
    <td>16</td>
    <td>peter</td>
    </tr>
    <tr>
    <th>2</th>
    <td>18</td>
    <td>mike</td>
    </tr>
    </tbody>
    </table>

    </div>

    生成一个副本,我们直接在副本上操作:

    df1 = df.copy()  # 生成副本,直接在副本上操作
    df2 = df.copy()
    
    df1
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: left;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>12</td>
    <td>xiaoming</td>
    </tr>
    <tr>
    <th>1</th>
    <td>16</td>
    <td>peter</td>
    </tr>
    <tr>
    <th>2</th>
    <td>18</td>
    <td>mike</td>
    </tr>
    </tbody>
    </table>

    </div>

    df1.assign(col3=lambda x: x.col1 / 2 + 20)  
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: left;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    <th>col3</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>12</td>
    <td>xiaoming</td>
    <td>26.0</td>
    </tr>
    <tr>
    <th>1</th>
    <td>16</td>
    <td>peter</td>
    <td>28.0</td>
    </tr>
    <tr>
    <th>2</th>
    <td>18</td>
    <td>mike</td>
    <td>29.0</td>
    </tr>
    </tbody>
    </table>

    </div>

    df1  # df1保持不变
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: left;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>12</td>
    <td>xiaoming</td>
    </tr>
    <tr>
    <th>1</th>
    <td>16</td>
    <td>peter</td>
    </tr>
    <tr>
    <th>2</th>
    <td>18</td>
    <td>mike</td>
    </tr>
    </tbody>
    </table>

    </div>

    df1["col3"] = df1["col1"].apply(lambda x:x / 2 + 20)
    
    df1  # df1已经发生了变化
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: left;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>col1</th>
    <th>col2</th>
    <th>col3</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>12</td>
    <td>xiaoming</td>
    <td>26.0</td>
    </tr>
    <tr>
    <th>1</th>
    <td>16</td>
    <td>peter</td>
    <td>28.0</td>
    </tr>
    <tr>
    <th>2</th>
    <td>18</td>
    <td>mike</td>
    <td>29.0</td>
    </tr>
    </tbody>
    </table>

    </div>

    我们发现:通过assign函数的操作,原数据是不变的,但是通过apply操作的数据已经变化了

    BMI

    最后在模拟一份数据,计算每个人的BMI。

    身体质量指数,是BMI指数,简称体质指数,是国际上常用的衡量人体胖瘦程度以及是否健康的一个标准。

    {BMI} = \frac {体重}{身高^2}

    其中:体重单位是kg,身高单位是m

    df2 = pd.DataFrame({
        "name":["xiaoming","xiaohong","xiaosu"],
        "weight":[78,65,87],
        "height":[1.82,1.75,1.89]
    })
    
    df2
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: left;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>name</th>
    <th>weight</th>
    <th>height</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>xiaoming</td>
    <td>78</td>
    <td>1.82</td>
    </tr>
    <tr>
    <th>1</th>
    <td>xiaohong</td>
    <td>65</td>
    <td>1.75</td>
    </tr>
    <tr>
    <th>2</th>
    <td>xiaosu</td>
    <td>87</td>
    <td>1.89</td>
    </tr>
    </tbody>
    </table>

    </div>

    # 使用assign函数实现
    
    df2.assign(BMI=df2["weight"] / (df2["height"] ** 2))
    
    image
    df2 # 不变
    

    <div>
    <style scoped>
    .dataframe tbody tr th:only-of-type {
    vertical-align: middle;
    }

    .dataframe tbody tr th {
        vertical-align: top;
    }
    
    .dataframe thead th {
        text-align: left;
    }
    

    </style>

    <table border="1" class="dataframe">
    <thead>
    <tr style="text-align: right;">
    <th></th>
    <th>name</th>
    <th>weight</th>
    <th>height</th>
    </tr>
    </thead>
    <tbody>
    <tr>
    <th>0</th>
    <td>xiaoming</td>
    <td>78</td>
    <td>1.82</td>
    </tr>
    <tr>
    <th>1</th>
    <td>xiaohong</td>
    <td>65</td>
    <td>1.75</td>
    </tr>
    <tr>
    <th>2</th>
    <td>xiaosu</td>
    <td>87</td>
    <td>1.89</td>
    </tr>
    </tbody>
    </table>

    </div>

    df2["BMI"] = df2["weight"] / (df2["height"] ** 2)
    
    df2  # df2生成了一个新的列:BMI
    
    image

    总结

    通过上面的例子,我们发现:

    1. 使用assign函数生成的DataFrame是不会改变原来的数据,这个DataFrame是新的
    2. assign函数能够同时操作多个列名,并且中间生成的列名能够直接使用
    3. assign和apply的主要区别在于:前者不改变原数据,apply函数是在原数据的基础上添加新列

    相关文章

      网友评论

          本文标题:图解Pandas的assign函数

          本文链接:https://www.haomeiwen.com/subject/ektigltx.html