Pandas数据处理

1、Apply自定义函数

1.1 apply介绍

pandas 的 apply() 函数可以作用于 Series 或者整个 DataFrame,功能也是自动遍历整个 Series 或者 DataFrame, 对每一个元素运行指定的函数。

  • Pandas提供了很多数据处理的API,但当提供的API不能满足需求的时候,需要自己编写数据处理函数, 这个时候可以使用apply函数

  • apply函数可以接收一个自定义函数, 可以将DataFrame的行/列数据传递给自定义函数处理

  • apply函数类似于编写一个for循环, 遍历行、列的每一个元素, 但比使用for循环效率高很多

1.2 Series的apply自定义函数【重点】

Series的apply自定义函数接收的参数x是一个数值

def my_exp(x,e):
    return x+e
# series.apply(自定义函数名, args=(参数1, 参数2, ...)) 
# args参数必须接收一个元祖;没有参数就不用写args=
df['列名'].apply(my_exp, args=(3,))

1.3 DataFrame的apply自定义函数【重点】

使用方法和Series的apply自定义函数的用法一致,比如对自定义函数传入多个参数的用法都是一样的

  • 默认按列遍历执行

    • df的apply自定义函数接收的参数x默认是一列数据

def my_exp2(x):
    return x+2
df.apply(my_exp2)

按行遍历执行

  • 参数axis=1使x的值是一行数据

def my_exp2(x):
    return x+2
df.apply(my_exp2, axis=1)

按df中的每一个值遍历执行

def my_exp2(x):
    return x+2
df.applymap(my_exp2)

1.4 函数向量化【知道】

np.vectorize()

def foo(x, y):
    if x != 0: # x,y都是series对象,不能和数字类型做比较判断
        return x + y
# foo(df['列名1'], df['列名2']) # 报错!

import numpy as np
bar = np.vectorize(foo)
bar(df['列名1'], df['列名2'])

对自定义函数使用装饰器

import numpy as np
@np.vectorize
def foo(x, y):
    if x != 0: # x,y都是series对象,不能和数字类型做比较判断
        return x + y
foo(df['列名1'], df['列名2'])

1.5 lambda匿名函数【重点】

  • 概念

    • 不用写函数名字的函数表达式,可以作为参数直接使用

  • 作用

    • 代码更加精简

    • 提高代码可读性

    • 不需要考虑函数命名的问题

  • 用法

# 关键字lambda表示匿名函数,冒号前是参数,可以有多个,用逗号隔开,冒号右边的返回值
df.apply(lambda x: x+1)

2、数据分组

2.1 agg和aggregate聚合【重点】

分组后单列使用多个聚合函数

  • 同时使用多个内置聚合函数或者numpy聚合函数,全部放入一个Python列表中, 然后把整个列表传入agg或aggregate中;返回以分组列作为索引,每一个聚合计算结果作为列的全新df

df.groupby('列名1').列名2.agg(['max', 'min']) 
# max, min 为pandas内置的聚合函数名
# 也可以传入numpy的聚合函数,np.mean,np.max
df.groupby('列名1').列名2.agg(['max',np.mean]) 

分组后对多列分别使用聚合函数

  • agg函数中可以传入字典,字典的key是df的列名,与key对应的value是pandas内置的聚合计算函数、其名称的字符串;;返回以分组列作为索引,每一个聚合计算结果作为列的全新df

df.groupby('列名1').agg({
    '列名2':'mean', 
    '列名3':'sum', 
    '列名4':np.max
})

分组后使用自定义聚合函数

def my_mean(values, args1, args2):
    '''自定义的计算平均值函数
    values是固定参数,为传入的series对象
    '''
    args1+args2
    n = len(values) # 获取数据条目数
    sum = 0
    for value in values:
        sum += value
    return(sum/n)
  
# 调用自定义函数
df.groupby('列名1')['列名2'].agg(my_mean, args1=xxx, args2=xxx)

2.2 transform转换【重点】

transform 转换,需要把DataFrame中的值传递给一个函数, 而后由该函数"转换"数据。

aggregate(聚合) 返回单个聚合值,分组列有多少组就返回多少条数据,但transform 不会减少数据量

  • 分组后使用内置函数

    • 根据列名1分组后,对列名2的值做聚合计算,返回series对象

df.groupby('列名1')['列名2'].transform('sum')
# sum是pandas内置聚合函数的函数名,求和
  • 分组后使用自定义函数

# 自定义一个计算函数
def foo(x, y):
    return x + y
df.groupby('列名1')['列名2'].transform(foo, y=3)

2.3 filter过滤【重点】

groupby方法后接filter方法,filter传入一个返回布尔值的匿名函数,该函数的入参就是groupby分组之后的每一组数据,返回False的数据会被过滤掉;最终返回新的df数据

df.groupby('列名').filter(匿名函数)

2.4 DataFrameGroupBy对象【了解】

查看groupby分组后每一个分组对象中数据所在的行

df.groupby('列名').groups

# 返回字典 {'Female': [198, 124, 101], 'Male': [24, 6, 153, 211, 176, 192, 9]}
# 那么df分组列中一定只有Female和Male两种数据
# 字典中的key是原df中分组列的类别值;value是一个python列表,里面的数字是是原始数据df的行索引值

根据分组列的列值获取分组对象并返回df

df.groupby('列名').get_group('分组列中的某个类别值')

分组对象只能遍历不能用下标获取具体的分组

for group in df.groupby('列名'):
    print(group)

### 以下代码是错误的!!!
df.groupby('列名')[0] 

3、数据透视表

数据透视表就是基于原数据表、按照一定规则呈现汇总数据;和excel的透视表在数据呈现上功能相同

3.1、privot_table()用法【重点】

df.pivot_table(
    index='列名1', # 分组的列名作为行索引
    columns='列名2', # 分组的列名作为列索引
    values='列名3',  # 要聚合的列
    aggfunc='内置聚合函数名', # 聚合函数 
    margins=True # 默认是False, 如果为True,就在最后一行和最后一列,按行按列分别执行aggfunc参数规定的聚合函数
)

pd.pivot_table(
  	data, # 要透视操作的df
    index='列名1', # 分组的列名作为行索引
    columns='列名2', # 分组的列名作为列索引
    values='列名3',  # 要聚合的列
    aggfunc='内置聚合函数名', # 聚合函数 
    margins=True # 默认是False, 如果为True,就在最后一行和最后一列,按行按列分别执行aggfunc参数规定的聚合函数
)
  • 使用说明:以列名1作为索引,根据列名2进行分组,对列名3使用pandas内置的聚合函数进行计算,返回新的df对象

  • 参数说明:

    • index:返回df的行索引,并依据其做分组;传入原始数据的列名

    • columns:返回df的列索引;传入原始数据的列名,根据该列做分组

    • values: 要做聚合操作的原始数据的列名

    • aggfunc:内置聚合函数名字符串

4、datetime数据类型【知道】

4.1 pandas中的数据转换成datetime

pd.to_datetime()

df['列名'] = pd.to_datetime(df['列名'])

加载数据时通过时parse_dates=[列下标/列名]

pd.read_csv('path', parse_dates=[列下标/'列名']) 

4.2 提取日期中的各个部分

时间戳类型对象提取日期中的各个部分

d = pd.to_datetime('2020-06-20') 
# d ==> Timestamp('2020-06-20 00:00:00')
d.year
d.month
d.day
d.hour
d.minute
d.second
d.quarter # 季度
d.weekday() # 星期几 0是星期一 1是星期二 6是星期日

df列中的时间日期对象提取日期中的各个部分

df['Date'].dt.year
df['Date'].dt.month
df['Date'].dt.day
df['Date'].dt.hour
df['Date'].dt.minute
df['Date'].dt.second
df['Date'].dt.quarter # 季度

4.3 日期运算和Timedelta类型

直接调用聚合函数

df['Date'].min() 

直接进行时间差运算

df['Date'] - df['Date'].min()
# 结果是timedelta类型

4.4 日期时间类型索引

时间序列数据,连续的按照一定时间距离或时间点记录的数据

  • 将datetime时间类型的列设为df的索引就变为DatetimeIndex类型此时可以分别按年月日取出数据

# 设定时间类型列为索引列
df.index = df['Date'] 
# 此时索引列值的样子是 2015-08-19
df['2016'] # 按年取子集df
df['2016-06'] # 按年月取子集df:所有符合条件的完整行数据
####注意!!!以上是日期时间类型行索引为连续的日期获取数据操作####

#当日期时间类型行索引不是连续的时候通过以下方法获取数据,df.loc[]
df.loc['2016']
df.loc['2016-06']
  • 将timedelta时间差类型的列设为df的索引就变为TimedeltaIndex类型此时可以按范围取出数据

# 设定timedelta时间差类型为索引列
df.index = df['Date'] - df['Date'].min()
# 此时索引列值的样子是
#0 days
#1 days
#2 days
#...
# 此时可以用范围取子集df:所有符合条件的完整行数据
tesla['0 days':'4 days']

 4.5 pd.date_range()

生成连续的DatetimeIndex类型数据

pd.date_range(start='2014-12-31', end='2015-01-05', freq='D')
# 参数freq='D'表示连续的日期
# 参数freq='B'表示只返回工作日

#### 返回如下 ####
###########################################
DatetimeIndex(
    [
        '2014-12-31', 
        '2015-01-01', 
        '2015-01-02', 
        '2015-01-03',
        '2015-01-04', 
        '2015-01-05'
    ],
    dtype='datetime64[ns]', 
    freq='D' # freq参数详见最后 时间周期参数
)
###########################################

4.6 df.reindex()

用连续的DatetimeIndex类型数据重建不连续的DatetimeIndex索引

df.index = df['Date']
date_range = pd.date_range(start='2014-12-31', end='2015-01-05', freq='D')
df = df.reindex(date_range)

4.7 df.between_time()

对DatetimeIndex作为索引的df可以按起止时间查询完整数据行

# between_time函数,include_end=False表示不包含结束时间,默认为True,同样也有include_start参数
df.between_time('4:00', '5:00', include_end=False)

4.8 df.at_time()

对DatetimeIndex作为索引的df可以按时间点采样返回完整数据行

df.at_time('5:47')

4.9 df.set_index()

将某列设置为df的行索引

df = df.set_index('列名')
# df.reset_index() 重置索引

4.10 df.sort_index()

对行索引进行排序操作

df = df.sort_index()
# 默认升序,ascending=False降序

4.11 df.resample()

按时间序列分组统计

df.resample('W').size() # 按每周统计数据的总数
df.resample('Q')['列名1', '列名2'].sum() # 按每季度对指定列进行聚合统计

你可能感兴趣的:(python,python,pandas)