• pandas数据处理(一)


    Pandas 名字衍生自术语 "panel data"(面板数据)和 "Python data analysis"(Python 数据分析)
    参考: https://pandas.pydata.org/ http://c.biancheng.net/pandas/plot.html

    1. 简介

    Pandas 的主要数据结构是 Series (一维数据)与 DataFrame(二维数据)。

    Series 是一种类似于一维数组的对象,它由一组数据(各种Numpy数据类型)以及一组与之相关的数据标签(即索引)组成。

    DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共同用一个索引)。

    2. 安装以及简单使用

    1. 安装
    pip install pandas
    
    1. 简单使用
    # author: qlq
    # date: 2022/8/17 18:09
    # desc:
    import pandas as pd
    print(pd.__version__)
    
    mydataset = {
      'sites': ["Google", "Runoob", "Wiki"],
      'number': [1, 2, 3]
    }
    
    myvar = pd.DataFrame(mydataset)
    
    print(myvar)
    

    结果:

    1.4.3
        sites  number
    0  Google       1
    1  Runoob       2
    2    Wiki       3
    

    3. Series

    Series 类似表格中的一个列(column),类似于一维数组,可以保存任何数据类型。

    Series 由索引(index)和列组成,函数如下:

    pandas.Series( data, index, dtype, name, copy)
    

    参数说明:

    data:一组数据(ndarray 类型)。
    
    index:数据索引标签,如果不指定,默认从 0 开始。
    
    dtype:数据类型,默认会自己判断。
    
    name:设置名称。
    
    copy:拷贝数据,默认为 False。
    

    简单使用:

    import pandas as pd
    
    a = [1, 2, 3]
    myvar = pd.Series(a)
    print(myvar)
    '''
    0    1
    1    2
    2    3
    dtype: int64
    '''
    # 0, 1, 2 列可以称为索引。 1, 2, 3 是数据。dtype: int64 是数据类型
    
    '''
    从上图可知,如果没有指定索引,索引值就从 0 开始,我们可以根据索引值读取数据:
    我们可以指定索引值,如下实例:
    '''
    a2 = ["Google", "Runoob", "Wiki"]
    myvar2 = pd.Series(a2, index = ["x", "y", "z"])
    print(myvar2)
    '''
    x    Google
    y    Runoob
    z      Wiki
    dtype: object
    '''
    print(myvar2["y"])
    '''
    Runoob
    '''
    
    '''
    可以使用 key/value 对象,类似字典来创建 Series:
    '''
    sites = {1: "Google", 2: "Runoob", 3: "Wiki"}
    myvar3 = pd.Series(sites)
    print(myvar3)
    '''
    1    Google
    2    Runoob
    3      Wiki
    dtype: object
    '''
    
    '''
    从上图可知,字典的 key 变成了索引值。如果我们只需要字典中的一部分数据,只需要指定需要数据的索引即可,如下实例:
    '''
    sites2 = {1: "Google", 2: "Runoob", 3: "Wiki"}
    myvar4 = pd.Series(sites2, index = [1, 2])
    print(myvar4)
    '''
    1    Google
    2    Runoob
    dtype: object
    '''
    
    '''
    设置 Series 名称参数:
    '''
    sites3 = {1: "Google", 2: "Runoob", 3: "Wiki"}
    myvar5 = pd.Series(sites3, index = [1, 2], name="RUNOOB-Series-TEST" )
    print(myvar5)
    '''
    1    Google
    2    Runoob
    Name: RUNOOB-Series-TEST, dtype: object
    '''
    

    4. DataFrame

    ​ DataFrame 是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型(数值、字符串、布尔型值)。DataFrame 既有行索引也有列索引,它可以被看做由 Series 组成的字典(共同用一个索引)。

    ​ 如下图:

    构造方法如下:

    pandas.DataFrame( data, index, columns, dtype, copy)
    

    参数解释:

    data:一组数据(ndarray、series, map, lists, dict 等类型)。
    
    index:索引值,或者可以称为行标签。
    
    columns:列标签,默认为 RangeIndex (0, 1, 2, …, n) 。
    
    dtype:数据类型。
    
    copy:拷贝数据,默认为 False。
    

    简单使用:

    # Pandas DataFrame 是一个二维的数组结构,类似二维数组。
    import pandas as pd
    data = [['Google',10],['Runoob',12],['Wiki',13]]
    df = pd.DataFrame(data,columns=['Site','Age'],dtype=float)
    print(df)
    '''
    常见属性和方法:
    T	行和列转置。
    axes	返回一个仅以行轴标签和列轴标签为成员的列表。
    dtypes	返回每列数据的数据类型。
    empty	DataFrame中没有数据或者任意坐标轴的长度为0,则返回True。
    ndim	轴的数量,也指数组的维数。
    shape	返回一个元组,表示了 DataFrame 维度。
    size	DataFrame中的元素数量。
    values	使用 numpy 数组表示 DataFrame 中的元素值。
    head()	返回前 n 行数据。
    tail()	返回后 n 行数据。
    shift()	将行或列移动指定的步幅长度
    '''
    print(df.axes)
    print(df.index)
    print(df.ndim)
    print(df.size)
    print(df.values)
    
    print("======1")
    # 使用 ndarrays 创建,ndarray 的长度必须相同, 如果传递了 index,则索引的长度应等于数组的长度。如果没有传递索引,则默认情况下,索引将是range(n),其中n是数组长度
    data1 = {'Site':['Google', 'Runoob', 'Wiki'], 'Age':[10, 12, 13]}
    df1 = pd.DataFrame(data1)
    print(df1)
    
    print("======2")
    # 可以使用字典(key/value),其中字典的 key 为列名。没有对应的部分数据为 NaN。
    data2 = [{'a': 1, 'b': 2},{'a': 5, 'b': 10, 'c': 20}]
    df2 = pd.DataFrame(data2)
    print(df2)
    
    print("======3")
    # 可以使用 loc 属性返回指定行的数据,如果没有设置索引,第一行索引为 0,第二行索引为 1,以此类推
    data3 = {
      "calories": [420, 380, 390],
      "duration": [50, 40, 45]
    }
    # 数据载入到 DataFrame 对象
    df3 = pd.DataFrame(data3)
    print(df3)
    # 返回第一行
    print(df3.loc[0])
    # 返回第二行
    print(df3.loc[1])
    # 返回第一行和第二行
    print(df3.loc[[0, 1]])
    
    print("======4")
    # 指定索引值,使用 loc 属性返回指定索对应到某一行
    data4 = {
      "calories": [420, 380, 390],
      "duration": [50, 40, 45]
    }
    df4 = pd.DataFrame(data4, index = ["day1", "day2", "day3"])
    print(df4)
    # 指定索引
    print(df4.loc["day2"])
    
    

    结果:

         Site   Age
    0  Google  10.0
    1  Runoob  12.0
    2    Wiki  13.0
    [RangeIndex(start=0, stop=3, step=1), Index(['Site', 'Age'], dtype='object')]
    RangeIndex(start=0, stop=3, step=1)
    2
    6
    [['Google' 10.0]
     ['Runoob' 12.0]
     ['Wiki' 13.0]]
    ======1
         Site  Age
    0  Google   10
    1  Runoob   12
    2    Wiki   13
    ======2
       a   b     c
    0  1   2   NaN
    1  5  10  20.0
    ======3
       calories  duration
    0       420        50
    1       380        40
    2       390        45
    calories    420
    duration     50
    Name: 0, dtype: int64
    calories    380
    duration     40
    Name: 1, dtype: int64
       calories  duration
    0       420        50
    1       380        40
    ======4
          calories  duration
    day1       420        50
    day2       380        40
    day3       390        45
    calories    380
    duration     40
    Name: day2, dtype: int64
    

    5. 操作csv、excel

    比如nba.csv 格式如下:

    Name,Team,Number,Position,Age,Height,Weight,College,Salary
    Avery Bradley,Boston Celtics,0.0,PG,25.0,6-2,180.0,Texas,7730337.0
    Jae Crowder,Boston Celtics,99.0,SF,25.0,6-6,235.0,Marquette,6796117.0
    John Holland,Boston Celtics,30.0,SG,27.0,6-5,205.0,Boston University,
    R.J. Hunter,Boston Celtics,28.0,SG,22.0,6-5,185.0,Georgia State,1148640.0
    ,,,,,,,,
    

    测试代码:

    # desc:
    import pandas as pd
    df = pd.read_csv('E:/nba.csv')
    # to_string() 用于返回 DataFrame 类型的数据,如果不使用该函数,则输出结果为数据的前面 5 行和末尾 5 行,中间部分以 ... 代替
    print(df.to_string())
    
    print("======1")
    # info() 方法返回表格的一些基本信息:
    print(df.info())
    print("======2")
    # head( n ) 和 tail(n) 查看指定开头和结尾数据。 默认n=5
    print(df.head())
    print("======3")
    print(df.tail())
    
    # to_XXX 转储文件
    df.to_csv("E:/nba1.csv")
    df.to_excel("E:/nba1.xlsx")
    

    结果:

                Name            Team  Number Position   Age Height  Weight            College     Salary
    0  Avery Bradley  Boston Celtics     0.0       PG  25.0    6-2   180.0              Texas  7730337.0
    1    Jae Crowder  Boston Celtics    99.0       SF  25.0    6-6   235.0          Marquette  6796117.0
    2   John Holland  Boston Celtics    30.0       SG  27.0    6-5   205.0  Boston University        NaN
    3    R.J. Hunter  Boston Celtics    28.0       SG  22.0    6-5   185.0      Georgia State  1148640.0
    4            NaN             NaN     NaN      NaN   NaN    NaN     NaN                NaN        NaN
    ======1
    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 5 entries, 0 to 4
    Data columns (total 9 columns):
     #   Column    Non-Null Count  Dtype  
    ---  ------    --------------  -----  
     0   Name      4 non-null      object 
     1   Team      4 non-null      object 
     2   Number    4 non-null      float64
     3   Position  4 non-null      object 
     4   Age       4 non-null      float64
     5   Height    4 non-null      object 
     6   Weight    4 non-null      float64
     7   College   4 non-null      object 
     8   Salary    3 non-null      float64
    dtypes: float64(4), object(5)
    memory usage: 488.0+ bytes
    None
    ======2
                Name            Team  Number  ... Weight            College     Salary
    0  Avery Bradley  Boston Celtics     0.0  ...  180.0              Texas  7730337.0
    1    Jae Crowder  Boston Celtics    99.0  ...  235.0          Marquette  6796117.0
    2   John Holland  Boston Celtics    30.0  ...  205.0  Boston University        NaN
    3    R.J. Hunter  Boston Celtics    28.0  ...  185.0      Georgia State  1148640.0
    4            NaN             NaN     NaN  ...    NaN                NaN        NaN
    
    [5 rows x 9 columns]
    ======3
                Name            Team  Number  ... Weight            College     Salary
    0  Avery Bradley  Boston Celtics     0.0  ...  180.0              Texas  7730337.0
    1    Jae Crowder  Boston Celtics    99.0  ...  235.0          Marquette  6796117.0
    2   John Holland  Boston Celtics    30.0  ...  205.0  Boston University        NaN
    3    R.J. Hunter  Boston Celtics    28.0  ...  185.0      Georgia State  1148640.0
    4            NaN             NaN     NaN  ...    NaN                NaN        NaN
    
    [5 rows x 9 columns]
    

    同理也有操作excel的相关API

    import pandas as pd
    df = pd.read_excel('E:/nba1.xlsx')
    # to_string() 用于返回 DataFrame 类型的数据,如果不使用该函数,则输出结果为数据的前面 5 行和末尾 5 行,中间部分以 ... 代替
    print(df.to_string())
    

    6. 操作JSON

    nested_list.json 代码如下:

    {
        "school_name": "ABC primary school",
        "class": "Year 1",
        "students": [
        {
            "id": "A001",
            "name": "Tom",
            "math": 60,
            "physics": 66,
            "chemistry": 61
        },
        {
            "id": "A002",
            "name": "James",
            "math": 89,
            "physics": 76,
            "chemistry": 51
        },
        {
            "id": "A003",
            "name": "Jenny",
            "math": 79,
            "physics": 90,
            "chemistry": 78
        }]
    }
    

    简单使用:

    # desc:
    import json
    
    import pandas as pd
    df = pd.read_json('E:/nested_list.json')
    print(df.to_string())
    
    print("======1")
    json_path = 'E:/nested_list.json'
    # 使用 Python JSON 模块载入数据
    # 展平数据
    with open(json_path,'r') as f:
        data = json.loads(f.read())
    df_nested_list = pd.json_normalize(data, record_path =['students'])
    print(df_nested_list)
    
    print("======2")
    # 使用 Python JSON 模块载入数据
    with open(json_path,'r') as f:
        data = json.loads(f.read())
    # 展平数据。
    # json_normalize() 使用了参数 record_path 并设置为 ['students'] 用于展开内嵌的 JSON 数据 students
    # 使用 meta 参数来显示这些元数据
    df_nested_list = pd.json_normalize(
        data,
        record_path =['students'],
        meta=['school_name', 'class']
    )
    print(df_nested_list)
    

    结果:

              school_name   class                                                                     students
    0  ABC primary school  Year 1    {'id': 'A001', 'name': 'Tom', 'math': 60, 'physics': 66, 'chemistry': 61}
    1  ABC primary school  Year 1  {'id': 'A002', 'name': 'James', 'math': 89, 'physics': 76, 'chemistry': 51}
    2  ABC primary school  Year 1  {'id': 'A003', 'name': 'Jenny', 'math': 79, 'physics': 90, 'chemistry': 78}
    ======1
         id   name  math  physics  chemistry
    0  A001    Tom    60       66         61
    1  A002  James    89       76         51
    2  A003  Jenny    79       90         78
    ======2
         id   name  math  physics  chemistry         school_name   class
    0  A001    Tom    60       66         61  ABC primary school  Year 1
    1  A002  James    89       76         51  ABC primary school  Year 1
    2  A003  Jenny    79       90         78  ABC primary school  Year 1
    

    7. 数据清洗

    主要包括空值处理、错误数据处理、重复数据处理。

    例如数据如下 property-data.csv

    上表包含了四种空数据:

    • n/a
    • NA
    • na

    1. 空值处理

    使用 dropna() 方法,语法格式如下:

    DataFrame.dropna(axis=0, how='any', thresh=None, subset=None, inplace=False)
    
    axis:默认为 0,表示逢空值剔除整行,如果设置参数 axis=1 表示逢空值去掉整列。
    how:默认为 'any' 如果一行(或一列)里任何一个数据有出现 NA 就去掉整行,如果设置 how='all' 一行(或列)都是 NA 才去掉这整行。
    thresh:设置需要多少非空值的数据才可以保留下来的。
    subset:设置想要检查的列。如果是多个列,可以使用列名的 list 作为参数。
    inplace:如果设置 True,将计算得到的值直接覆盖之前的值并返回 None,修改的是源数据。
    

    1. 检测空值

    Pandas 把 n/a 和 NA 当作空数据,na 不是空数据。 可以通过自己指定然后设置为空的值。

    import pandas as pd
    csv_path = 'E:/property-data.csv'
    df = pd.read_csv(csv_path)
    print (df['NUM_BEDROOMS'])
    #  isnull() 判断各个单元格是否为空
    # 把 n/a 和 NA 当作空数据,na 不是空数据
    print (df['NUM_BEDROOMS'].isnull())
    
    # 自定义为空值的值
    print("======1")
    missing_values = ["n/a", "na", "--"]
    df1 = pd.read_csv(csv_path, na_values = missing_values)
    print (df1['NUM_BEDROOMS'])
    print (df1['NUM_BEDROOMS'].isnull())
    

    结果:

    0      3
    1      3
    2    NaN
    3      1
    4      3
    5    NaN
    6      2
    7      1
    8     na
    Name: NUM_BEDROOMS, dtype: object
    0    False
    1    False
    2     True
    3    False
    4    False
    5     True
    6    False
    7    False
    8    False
    Name: NUM_BEDROOMS, dtype: bool
    ======1
    0    3.0
    1    3.0
    2    NaN
    3    1.0
    4    3.0
    5    NaN
    6    2.0
    7    1.0
    8    NaN
    Name: NUM_BEDROOMS, dtype: float64
    0    False
    1    False
    2     True
    3    False
    4    False
    5     True
    6    False
    7    False
    8     True
    Name: NUM_BEDROOMS, dtype: bool
    

    2. 删除包含空值的行

    import pandas as pd
    csv_path = 'E:/property-data.csv'
    
    # 删除包含空数据的行
    # 默认情况下,dropna() 方法返回一个新的 DataFrame,不会修改源数据。 如果要修改源数据 DataFrame, 可以使用 inplace = True 参数:
    df = pd.read_csv(csv_path)
    new_df = df.dropna()
    print(new_df.to_string())
    

    结果:

               PID  ST_NUM    ST_NAME OWN_OCCUPIED NUM_BEDROOMS NUM_BATH SQ_FT
    0  100001000.0   104.0     PUTNAM            Y            3        1  1000
    1  100002000.0   197.0  LEXINGTON            N            3      1.5    --
    8  100009000.0   215.0    TREMONT            Y           na        2  1800
    

    3. 移除指定列有空值的行

    import pandas as pd
    
    csv_path = 'E:/property-data.csv'
    df = pd.read_csv(csv_path)
    df.dropna(subset=['ST_NUM'], inplace = True)
    print(df.to_string())
    

    结果:

               PID  ST_NUM    ST_NAME OWN_OCCUPIED NUM_BEDROOMS NUM_BATH SQ_FT
    0  100001000.0   104.0     PUTNAM            Y            3        1  1000
    1  100002000.0   197.0  LEXINGTON            N            3      1.5    --
    3  100004000.0   201.0   BERKELEY           12            1      NaN   700
    4          NaN   203.0   BERKELEY            Y            3        2  1600
    5  100006000.0   207.0   BERKELEY            Y          NaN        1   800
    7  100008000.0   213.0    TREMONT            Y            1        1   NaN
    8  100009000.0   215.0    TREMONT            Y           na        2  1800
    

    4. fillna 方法替换空值

    import pandas as pd
    
    csv_path = 'E:/property-data.csv'
    df = pd.read_csv(csv_path)
    df.fillna('12345', inplace = True)
    # 也可以指定列
    # df['PID'].fillna(12345, inplace = True)
    print(df.to_string())
    

    结果:

               PID ST_NUM     ST_NAME OWN_OCCUPIED NUM_BEDROOMS NUM_BATH  SQ_FT
    0  100001000.0  104.0      PUTNAM            Y            3        1   1000
    1  100002000.0  197.0   LEXINGTON            N            3      1.5     --
    2  100003000.0  12345   LEXINGTON            N        12345        1    850
    3  100004000.0  201.0    BERKELEY           12            1    12345    700
    4        12345  203.0    BERKELEY            Y            3        2   1600
    5  100006000.0  207.0    BERKELEY            Y        12345        1    800
    6  100007000.0  12345  WASHINGTON        12345            2   HURLEY    950
    7  100008000.0  213.0     TREMONT            Y            1        1  12345
    8  100009000.0  215.0     TREMONT            Y           na        2   1800
    

    5. 均值、中位数、众数

    mean()median()mode() 方法计算列的均值(所有值加起来的平均值)、中位数值(排序后排在中间的数)和众数(出现频率最高的数)

    一般用上面的数来替换空值。

    import pandas as pd
    
    csv_path = 'E:/property-data.csv'
    df = pd.read_csv(csv_path)
    # 均值
    print(df["ST_NUM"].mean())
    # 中位数
    print(df["ST_NUM"].median())
    # 众数
    print(df["ST_NUM"].mode())
    

    结果:

    191.42857142857142
    203.0
    0    104.0
    1    197.0
    2    201.0
    3    203.0
    4    207.0
    5    213.0
    6    215.0
    

    2. 清洗错误数据

    1. 定位数据然后修改

    import pandas as pd
    
    person = {
      "name": ['Google', 'Runoob' , 'Taobao'],
      "age": [50, 40, 12345]    # 12345 年龄数据是错误的
    }
    df = pd.DataFrame(person)
    df.loc[2, 'age'] = 30 # 修改数据
    print(df.to_string())
    

    结果:

         name  age
    0  Google   50
    1  Runoob   40
    2  Taobao   30
    

    2. 通过条件修改

    import pandas as pd
    
    person = {
      "name": ['Google', 'Runoob' , 'Taobao'],
      "age": [50, 200, 12345]
    }
    # 将 age 大于 120 的设置为 120:
    df = pd.DataFrame(person)
    for x in df.index:
      if df.loc[x, "age"] > 120:
        df.loc[x, "age"] = 120
    
    print(df.to_string())
    

    3. 删除错误的行数据

    import pandas as pd
    
    person = {
      "name": ['Google', 'Runoob' , 'Taobao'],
      "age": [50, 200, 12345]
    }
    # 将 age 大于 120 的数据删除
    df = pd.DataFrame(person)
    for x in df.index:
      if df.loc[x, "age"] > 120:
        df.drop(x, inplace = True)
    
    print(df.to_string())
    

    3. 重复数据处理

    清洗重复数据,可以使用 duplicated()drop_duplicates() 方法

    如果对应的数据是重复的,duplicated() 会返回 True,否则返回 False。

    1. 检测重复数据
    import pandas as pd
    person = {
      "name": ['Google', 'Runoob', 'Runoob', 'Taobao'],
      "age": [50, 40, 40, 23]
    }
    df = pd.DataFrame(person)
    print(df.to_string())
    print("======1")
    print(df.duplicated())
    

    结果:

         name  age
    0  Google   50
    1  Runoob   40
    2  Runoob   40
    3  Taobao   23
    ======1
    0    False
    1    False
    2     True
    3    False
    dtype: bool
    
    1. 删除重复数据
    import pandas as pd
    person = {
      "name": ['Google', 'Runoob', 'Runoob', 'Taobao', 'JD'],
      "age": [50, 40, 40, 23, 50]
    }
    df = pd.DataFrame(person)
    
    print(df.to_string())
    print("======1")
    # 按全部的列去重
    df.drop_duplicates(inplace = True)
    print(df.to_string())
    print("======1")
    # 按指定的列进行去重
    df.drop_duplicates(subset= ['age'], inplace = True)
    print(df.to_string())
    

    结果:

         name  age
    0  Google   50
    1  Runoob   40
    2  Runoob   40
    3  Taobao   23
    4      JD   50
    ======1
         name  age
    0  Google   50
    1  Runoob   40
    3  Taobao   23
    4      JD   50
    ======1
         name  age
    0  Google   50
    1  Runoob   40
    3  Taobao   23
    
  • 相关阅读:
    我们可以用SharePoint做什么
    HTML <!DOCTYPE> 标签
    一种支持任意尺寸的图片滑动(上下左右滑动)效果
    CSS选择器
    用css截取字符 css排版隐藏溢出文本
    Web前端行业的了解
    java07课堂作业
    设计模式原型模式
    设计模式建造者
    设计模式抽象工厂
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/16600489.html
Copyright © 2020-2023  润新知