Pandas入门

Pandas

此文稍长,但是包括了pandas的基础入门使用以及一些进阶部分:时间序列,数据清洗预处理等操作,当然要学习了解更多细节和操作去翻阅Pandas官方的操作手册也是必不可少的。

基础部分

  1. 导入pandas import pandas as pd
  2. 查看版本信息 pd.__version__

Series数据类型

创建Series

  1. 从列表中创建Series: S = pd.Series(data=['1','2','3','4'],index=['a','b','c','d'],name='CreatedSeries')

  2. 从字典中创建:

    d = {'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5}
    s2 = pd.Series(d)
    
  3. 从Ndarrray创建

    import numpy as np
    n = np.random.randn(5)
    s3 = pd.Series(data=n) 
    

Series基本操操作

  1. 修改索引:S.index=[...],Series.reindex([...])
  2. 纵向拼接:pd.concat([s1,s2])
  3. 按指定索引
    1. 删除:S.drop('a')
    2. 修改:S['d']=1S.loc['d']=1
    3. 查找 :S.['d']S.loc['d']
    4. 切片操作 S[:] 参考列表切片操作

Series运算

​ 按照索引进行计算,所以不同则为NaN空值,下面以S与自身运算为例

  • 四则运算如下:

    S.add(S)
    S.sub(S)
    S.mul(S)
    S.div(S)
    
  • 求中位数、求和、最值:

    res6 = S.median() # 中位数
    res7 = S.sum() # 求和
    res8 = S.max() # 最大值
    res9 = S.min() # 最小值
    

DataFrame数据类型

创建DataFrame

  1. 从Numpy数组创建:

    dates = pd.date_range('today', periods=6)  # 定义时间序列作为 index
    num_arr = np.random.randn(6, 4)  # 传入 numpy 随机数组
    column_name = ['A', 'B', 'C', 'D'] 
    df1 = pd.DataFrame(data=num_arr,index=dates,columns=column_name)
    
  2. 通过数组字典创建:

    data = {'animal': ['cat', 'cat', 'snake', 'dog', 'dog', 'cat', 'snake', 'cat', 'dog', 'dog'],
            'age': [2.5, 3, 0.5, np.nan, 5, 2, 4.5, np.nan, 7, 3],
            'visits': [1, 3, 2, 3, 2, 3, 1, 1, 2, 1],
            'priority': ['yes', 'yes', 'no', 'yes', 'no', 'no', 'no', 'yes', 'no', 'no']}
    
    labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
    df2 = pd.DataFrame(data,index=labels)
    
  3. 查看DataFrame数据类型: df2.dtypes

DataFrame基本操作

  1. 了解陌生数据集结构(尤其是数据量大的数据)

    # 查看前5行
    df2.head() # 可以通过传递整数参数来指定显示行数
    # 查看后3行
    df2.tail(3) # 默认显示后5行
    
  2. 查看索引:df1.index

  3. 查看列名:df2.columns

  4. 查看数值:df2.values

  5. 查看统计数据:df2.describe(include='all') # 默认只统计数值列数据,查看所有列就需要参数 include='all'

  6. 转置操作:df1.T

  7. 按列排序:df1.sort_values(by='A',ascending=False) #以A列的值降序排列

  8. 切片操作:df1[:6:2]

  9. 通过标签查询单列和多列

    df1['A'] # 查询A列
    df1.A # 查询A列等价写法
    df1[['A','B']] # 查询A列和B列
    
  10. 多条件查询

    df1[(df1['A']>0) & (df1['B']<0)]
    
  11. 按位置查询
    .loc[]方法用于根据标签名称索引,行和列对应的名称
    .iloc[]方法用于根据整数位置索引,行和列都是从0开始编号

    row = df1.iloc[1] # 按行位置查询
    col = df1.iloc[:,2] # 按列位置查询
    arr = df1.iloc[:5,:3] # 前五行前三列
    
  12. 副本拷贝:df3= df2.copy # 从df2生成DataFrame副本df3

  13. 判断元素是否为空:

    df2.isnull() # 判断整个df2元素是否为空值
    df2['age'].isnull() # 判断df2中的age列元素是否为空值
    
  14. 添加列数据:

    num = pd.Series([0,1,2,3,4,5,6,7,8,9],index=df3.index) # 需要插入的列
    df3['No.']=num # num插入到df3中命名为’No.‘
    
  15. 数据修改:

    1. 根据下标值:df2.iloc[2,1]=1 # 修改了第三行第二列的数据df2.iat[2,1]=1 # 等价与前一种
    2. 根据标签:df2.loc['a','age']=3 # 修改了名为'a’行,‘age'列的数据
  16. 求和、求平均值操作等

    df2.median()
    df2['age'].sum()
    
  17. 字符串操作

    1. 大小写转换:

      string = pd.Series(['A', 'B', 'C', 'Aaba', 'Baca',np.nan, 'CABA', 'dog', 'cat'])
      print(string)
      string.str.lower() # 字符串转换为小写
      string.str.upper() # 将字符串换为大写
      
    2. 分割字符串:

      import pandas as pd
      
      # 创建一个包含字符串的Series
      data = pd.Series(['apple,banana,cherry', 'date,fig'])
      print(data)
      
      # 使用.str.split()方法按逗号分割字符串
      split_data = data.str.split(',')
      print(split_data)
      
  18. 缺失值操作:

    1. 检测缺失值:isna()notna():这两个方法用于检测缺失值。isna()返回一个布尔值Series,指示每个元素是否为缺失值。notna()返回一个布尔值Series,指示每个元素是否不是缺失值

      data = pd.Series([1, 2, np.nan, None])
      print(data.isna())
      print(data.notna())
      
    2. 删除缺失值:dropna():该方法用于删除包含缺失值的行或列。默认情况下,它会删除包含任何缺失值的行。可以使用axis参数指定删除的轴,axis=0表示删除行,axis=1表示删除列

      data = pd.DataFrame({'A': [1, 2, np.nan],
                           'B': [4, np.nan, 6],
                           'C': [np.nan, 8, 9]})
      print(data)
      cleaned_data = data.dropna()
      print(cleaned_data)
      cleaned_data_col = data.dropna(axis=1)
      print(cleaned_data_col)
      
  19. 指定列对齐:

    # 创建两个示例DataFrame
    df1 = pd.DataFrame({'A': [1, 2, 3],
                        'B': [4, 5, 6]})
    df2 = pd.DataFrame({'C': [7, 8, 9],
                        'D': [10, 11, 12]})
    
    # 按'A'列对齐两个DataFrame
    df1_aligned, df2_aligned = df1.align(df2, join='inner', axis=0, level=None, copy=False)
    
    print(df1_aligned)
    print(df2_aligned)
    
  20. 列名的重命名:

    import pandas as pd
    
    # 创建示例数据帧
    df = pd.DataFrame({'A': [1, 2, 3], 'B': [4, 5, 6]})
    
    # 定义新的列名列表
    new_column_names = ['X', 'Y']
    
    # 使用rename()函数重命名列
    df = df.rename(columns=dict(zip(df.columns, new_column_names)))
    print(df)
    

文件读取和写入操作

  1. 读取:pd.read_csv()pd.read_excel()等方法对不同文件读取
  2. 写入:df.to_excel()df.to_json()等方法进行写入,此处的df是一个DataFrame对象

进阶部分:

时间序列索引

  1. 建立一个以 2018 年每一天为索引,值为随机数的 Series:
import pandas as pd
import numpy as np

dti = pd.date_range(start='2018-01-01', end='2018-12-31', freq='D')
s = pd.Series(np.random.rand(len(dti)), index=dti)
  1. 统计每一个周三对应值的和:

    # 周一从 0 开始
    s[s.index.weekday == 2].sum()
    
  2. 统计每个月的平均值:

    s.resample('M').mean() 
    

    pandas中的resample()函数对时间序列数据进行重采样

  3. 时间转换:

    s = pd.date_range('today', periods=100, freq='S')
    
    ts = pd.Series(np.random.randint(0, 500, len(s)), index=s)
    
    sum1 = ts.resample('Min').sum()
    sum2 = ts.resample('H').sum()
    ''' 注意使用sum()重采样聚合后 sum1与sum2值相等 '''
    
  4. 时间标准转换:

    s = pd.date_range('today', periods=1, freq='D')  # 获取当前时间
    ts = pd.Series(np.random.randn(len(s)), s)  # 随机数值
    ts_utc = ts.tz_localize('UTC')  # 转换为 UTC 时间
    ts_utc.tz_convert('Asia/Shanghai') # 转换为上海时间
    
  5. 不同时间表示方式转换:

    rng = pd.date_range('1/1/2018', periods=5, freq='M')
    ts = pd.Series(np.random.randn(len(rng)), index=rng)
    print(ts)
    ps = ts.to_period()
    print(ps)
    ps.to_timestamp()
    

Series 多重索引

  1. 创建多重索引:

    letters = ['A', 'B', 'C']
    numbers = list(range(10))
    
    mi = pd.MultiIndex.from_product([letters, numbers])  # 设置多重索引
    s = pd.Series(np.random.rand(30), index=mi)  # 随机数
    
  2. 根据多重索引查询:

    # 查询索引为 1,3,6 的值
    s.loc[:, [1, 3, 6]]
    
  3. 多重索引切片:

    s.loc[pd.IndexSlice[:'B', 5:]]
    

DataFrame多重索引

  1. 创建带有多重索引的DataFrame:

    frame = pd.DataFrame(np.arange(12).reshape(6, 2),
                         index=[list('AAABBB'), list('123123')],
                         columns=['hello', 'shiyanlou'])
    
  2. 多重索引设置列名称:

    frame.index.names = ['first', 'second']
    
  3. 多重索引分组求和:

    frame.groupby('firsr').sum
    
  4. 行列名称转换:

    print(frame)
    frame.stack()
    
  5. 索引转换:

    frame.unstack()
    
  6. 条件查找

    # 示例数据
    data = {'animal': ['cat', 'cat', 'snake', 'dog', 'dog', 'cat', 'snake', 'cat', 'dog', 'dog'],
            'age': [2.5, 3, 0.5, np.nan, 5, 2, 4.5, np.nan, 7, 3],
            'visits': [1, 3, 2, 3, 2, 3, 1, 1, 2, 1],
            'priority': ['yes', 'yes', 'no', 'yes', 'no', 'no', 'no', 'yes', 'no', 'no']}
    
    labels = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
    df = pd.DataFrame(data, index=labels)
    # 单个条件查询
    df[df['age']>3]
    # 多个条件查询
    df[(df['animal'] == 'cat') & (df['age'] < 3)]
    
  7. 按关键字查询:

    df[df['animal'].isin(['cat','dog'])]
    
  8. 按标签及列名查询:

    df.loc[df.index[[3,4,8]],['animal','age']]
    
  9. 多条件排序

 ```python
 # 字段`age`降序,`visits`升序来进行排序
 df.sort_values(by=['age','visits'], ascending=[False,True])
 ```
  1. 多值替换:对某一列数据使用map函数进行替换

    df['priority'].map({'yes':True, 'no':False})
    
  2. 分组求和

    df.groupby('animal').sum()
    df.groupby(['animal','age']).sum()
    
  3. 拼接多个DataFrame

    temp_df1 = pd.DataFrame(np.random.randn(5, 4))  # 生成由随机数组成的 DataFrame 1
    temp_df2 = pd.DataFrame(np.random.randn(5, 4))  # 生成由随机数组成的 DataFrame 2
    temp_df3 = pd.DataFrame(np.random.randn(5, 4))  # 生成由随机数组成的 DataFrame 3
    
    print(temp_df1)
    print(temp_df2)
    print(temp_df3)
    
    pieces = [temp_df1, temp_df2, temp_df3]
    pd.concat(pieces)
    # 等价于 pd.concat([temp_df1, temp_df2, temp_df3])
    
  4. 找出和最小的列:

    df = pd.DataFrame(np.random.random(size=(5, 10)), columns=list('abcdefghij'))
    # idxmax(),idmin() 返回最大最小值的索引值
    df.sum().idxmin()
    
  5. 每个元素减去每一行的平均值:

    df = pd.DataFrame(np.random.random(size=(5, 3)))
    # 相当于复合运算
    df.sub(df.mean(axis=1), axis=0)
    
  6. DataFrame分组,并得到每一组中最大三个数之和:

    df = pd.DataFrame({'A': list('aaabbcaabcccbbc'),
                       'B': [12, 345, 3, 1, 45, 14, 4, 52, 54, 23, 235, 21, 57, 3, 87]})
    print(df)
    df.groupby('A')['B'].nlargest(3).sum(level=0)
    
  7. DataFrame 分组,并得到每一组中最大三个数之和

    df = pd.DataFrame({'A': list('aaabbcaabcccbbc'),
                       'B': [12, 345, 3, 1, 45, 14, 4, 52, 54, 23, 235, 21, 57, 3, 87]})
    df.groupby('A')['B'].nlargest(3).sum(level=0)
    df.nlargest(3,'B') # 获取df中B列值最大的前三行
    

透视表

当分析庞大的数据时,为了更好的发掘数据特征之间的关系,且不破坏原数据,就可以利用透视表 pivot_table 进行操作

  1. 透视表的创建:

    df = pd.DataFrame({'A': ['one', 'one', 'two', 'three'] * 3,
                       'B': ['A', 'B', 'C'] * 4,
                       'C': ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,
                       'D': np.random.randn(12),
                       'E': np.random.randn(12)})
    
    pd.pivot_table(df, index=['A', 'B', 'C'])
    
  2. 按照指定列进行聚合:

    # 将以D列聚合,按照A,B列为索引进行聚合,聚合的方式为默认求平均值
    pd.pivot_table(df, values=['D'], index=['A', 'B'])
    
  3. 透视表聚合方式定义:

    # 当 aggfunc 是一个函数列表时,将同时应用多个聚合函数,并返回一个具有多级列索引的数据框
    pd.pivot_table(df, values=['D'], index=['A', 'B'], aggfunc=[np.sum, len])
    # aggfunc=[np.sum, len] 表示要对值进行两个聚合操作,即求和和计数。np.sum 是一个函数,表示要计算每个组合
    
  4. 透视表利用额外列进行辅助分割:

    #`D` 列按照 `A,B` 列进行聚合时,若关心 `C` 列对 `D` 列的影响,可以加入 `columns` 值进行分析
    pd.pivot_table(df, values=['D'], index=['A', 'B'],
                   columns=['C'], aggfunc=np.sum)
    
  5. 透视表中对缺省值处理:

    # 在透视表中由于不同的聚合方式,相应缺少的组合将为缺省值,可以加入 `fill_value` 对缺省值处理
    pd.pivot_table(df, values=['D'], index=['A', 'B'],
                   columns=['C'], aggfunc=np.sum, fill_value=0)
    

绝对类型

在数据的形式上主要包括数量型和性质型,数量型表示着数据可数范围可变,而性质型表示范围已经确定不可改变,绝对型数据就是性质型数据的一种

  1. 绝对型数据定义:

    df = pd.DataFrame({"id": [1, 2, 3, 4, 5, 6], "raw_grade": [
                      'a', 'b', 'b', 'a', 'a', 'e']})
    df["grade"] = df["raw_grade"].astype("category"
    
  2. 对绝对型数据重命名:

    df["grade"].cat.categories = ["very good", "good", "very bad"]
    
  3. 绝对型数据其他操作:

    # 排序
    df.sort_values(by="grade")
    # 分组
    df.groupby("grade").size()
    

数据清洗&预处理

经常得到的数据不符合最终处理的数据要求,包括了缺省值以及坏的数据,需要我们对数据进行清洗

  1. 缺失值拟合

    df = pd.DataFrame({'From_To': ['LoNDon_paris', 'MAdrid_miLAN', 'londON_StockhOlm',
                                   'Budapest_PaRis', 'Brussels_londOn'],
                       'FlightNumber': [10045, np.nan, 10065, np.nan, 10085],
                       'RecentDelays': [[23, 47], [], [24, 43, 87], [13], [67, 32]],
                       'Airline': ['KLM(!)', '<Air France> (12)', '(British Airways. )',
                                   '12. Air France', '"Swiss Air"']})
    # 对FlightNumber中缺失的数据进行线性填充,并让数据为int类型
    df['FlightNumber'] = df['FlightNumber'].interpolate().astype(int)
    
    
  2. 数据列拆分

    # 将上一步生成的df中的From_To列通过split进行拆分为独立两列为新表
    temp = df.From_To.str.split('_', expand=True)
    temp.columns = ['From', 'To']
    
  3. 字符标准化

    # 对地名姓名进行标准化处理
    temp['From'] = temp['From'].str.capitalize()
    temp['To'] = temp['To'].str.capitalize()
    
  4. 删除坏数据加入整理好的数据

    # 将原来的From_to列删除,加入整理好的From和to列
    df = df.drop('From_To', axis=1)
    df = df.join(temp)
    print(df)
    
  5. 去除多余字符

    df['Airline'] = df['Airline'].str.extract(
        '([a-zA-Z\s]+)', expand=False).str.strip()
    
    
  6. 格式规范:
    上面df中的RencentDelays中记录的方式为列表类型,但是列表的长度不一,后期处理分析会比较麻烦,此时将其拆开,去除列表中相同位置元素作为一列,若为空值用NaN代替

    delays = df['RecentDelays'].apply(pd.Series)
    
    delays.columns = ['delay_{}'.format(n)
                      for n in range(1, len(delays.columns)+1)]
    
    df = df.drop('RecentDelays', axis=1).join(delays)
    
  7. 信息区间划分:

    # 将grades按照是否大于60来划分
    df = pd.DataFrame({'name': ['Alice', 'Bob', 'Candy', 'Dany', 'Ella',
                                'Frank', 'Grace', 'Jenny'],
                       'grades': [58, 83, 79, 65, 93, 45, 61, 88]})
    
    
    def choice(x):
        if x > 60:
            return 1
        else:
            return 0
    
    
    df.grades = pd.Series(map(lambda x: choice(x), df.grades))
    
  8. 数据区重复:

    df = pd.DataFrame({'A': [1, 2, 2, 3, 4, 5, 5, 5, 6, 7, 7]})
    # 将A列中连续重复的数据清除
    df.loc[df['A'].shift() != df['A']]
    
posted @ 2023-11-09 16:41  Pennaa  阅读(42)  评论(0编辑  收藏  举报