饮冰三年-人工智能-Pandas-79-Pandas 数据处理
上一篇:饮冰三年-人工智能-Pandas-78-Pandas 新增、统计、排序
数据准备可参考:饮冰三年-人工智能-Django淘宝拾遗-75-数据准备
一、对缺失值处理
1.1 检测
- Isnull 和 notnull:检查是否是空值,可用于series和dataframe
1.1.1 用于series
from api_service.pandas_ import get_data_from_db df = get_data_from_db() # 01-检测(series) series_result = df.loc[df["id"] > 476, "course_name"] print(series_result) # 同样类似 方法 notnull print(series_result.isnull())
470 None 471 None 472 None 473 英语-挖 474 挖掘机实操-挖 475 挖掘机实操-挖 476 挖掘机实操-挖 477 挖掘机实操-挖 478 挖掘机实操-挖 479 挖掘机实操-挖 Name: course_name, dtype: object 470 True 471 True 472 True 473 False 474 False 475 False 476 False 477 False 478 False 479 False
1.1.2 用于DataFrame
# 01-检测(dataframe) dataframe_result = df.loc[df["id"] > 476, ["course_name", "score_total"]] print(dataframe_result) # 同样类似 方法 notnull print(dataframe_result.notnull())
course_name score_total 470 None 70 471 None 100 472 None 10 473 英语-挖 90 474 挖掘机实操-挖 5 475 挖掘机实操-挖 60 476 挖掘机实操-挖 9 477 挖掘机实操-挖 100 478 挖掘机实操-挖 80 479 挖掘机实操-挖 90 course_name score_total 470 False True 471 False True 472 False True 473 True True 474 True True 475 True True 476 True True 477 True True 478 True True 479 True True
1.2 丢弃
- dropna:丢弃、删除缺失值
- axis:删除行还是列 {0 or ‘index’,1 or ‘columns’} default 为0
- how:如果等于any:任何值为空都删除。如果为all:所有值为空才删除
- inplace:如果为True则替换当前df,否则返回新的df
def drop(): # 02-处理方式 之 丢弃 dropna """ 丢弃、删除缺失值 .axis: 删除行还是列 {0 or "index", 1 or "columns"} 默认是0 .how: 如果等于any,任何值为空都删除, 如果为all,所有值为空才删除 .inplace: True:替换当前df,否则返回新的df """ dataframe_result = df.loc[df["id"] > 476, ["course_name", "score_total"]] # 如果列中有任意一个值为空的就删除这一行 dataframe_result.dropna(axis="index", how="any", inplace=True) print(dataframe_result)
course_name score_total
473 英语-挖 90
474 挖掘机实操-挖 5
475 挖掘机实操-挖 60
476 挖掘机实操-挖 9
477 挖掘机实操-挖 100
478 挖掘机实操-挖 80
479 挖掘机实操-挖 90
1.3 填充
- fillna:填充空值
- value:用于填充的值,可以是单个值。或者是字典(key为列名,value是值)
- method
- ffill:forward fill:使用前一个不为空的值填充
- bfill:backword fill:使用后一个不为空的值填充
- axis:按行还是按列填充
- inplace:如果为True则替换当前df,否则返回新的df
def fill(): # 03-处理方式 之 填充 fillna dataframe_result = df.loc[df["id"] > 476, ["id", "course_name", "score_total", "exams_version"]] print("-----原始数据------") print(dataframe_result) # 03-01 将分数列为空的填充为0分 (以自典形式填充) dataframe_result.fillna({"score_total": 0}, inplace=True) # 03-02 将课程列为空的填充为 英语-挖 (以值形式填充) dataframe_result.loc[:, 'course_name'] = dataframe_result['course_name'].fillna("英语-挖") # 03-03 将考试版本列为空的填充为 上一个相邻的值 (以method形式填充) dataframe_result.loc[:, 'exams_version'] = dataframe_result['exams_version'].fillna(method='ffill') print("-----填充后的数据------") print(dataframe_result)
-----原始数据------ id course_name score_total exams_version 470 477 None NaN NaN 471 478 None NaN 1.0 472 479 None NaN NaN 473 480 英语-挖 90.0 1.0 474 481 挖掘机实操-挖 5.0 1.0 475 482 挖掘机实操-挖 60.0 1.0 476 483 挖掘机实操-挖 9.0 1.0 477 484 挖掘机实操-挖 100.0 1.0 478 485 挖掘机实操-挖 80.0 1.0 479 486 挖掘机实操-挖 90.0 1.0 -----填充后的数据------ id course_name score_total exams_version 470 477 英语-挖 0.0 NaN 471 478 英语-挖 0.0 1.0 472 479 英语-挖 0.0 1.0 473 480 英语-挖 90.0 1.0 474 481 挖掘机实操-挖 5.0 1.0 475 482 挖掘机实操-挖 60.0 1.0 476 483 挖掘机实操-挖 9.0 1.0 477 484 挖掘机实操-挖 100.0 1.0 478 485 挖掘机实操-挖 80.0 1.0 479 486 挖掘机实操-挖 90.0 1.0
二、字符串处理
Pandas 的字符串处理:官网
- 使用方法:先获取 Series 的 str 属性,然后再在属性上调用函数
- 只能在字符串列上使用
- 否则会报错 AttributeError: Can only use .str accessor with string values!
- 只能在series上使用,DataFrame上没有str属性和处理方法
- Series.str 并不是Python原生字符串,而是自己的一套方法,不过大部分和原生str很相似。
使用示例
1 获取 Series 的 str 属性,使用常见的字符串处理函数
2 使用 str 的 startswith contains 等得到的是 bool 的 series,可做条件查询
3 使用 str 可以进行链式操作 ps:需要注意是的链式操作之间需要使用str属性
def str_proces(): d_f = df.loc[df["id"] > 476, ["course_name"]] # d_f['course_name'].str.len() # 为了方便查看, # 1 获取 Series 的 str 属性,使用常见的字符串处理函数 d_f.loc[:, "课程名称长度"] = d_f['course_name'].str.len() print("11" * 100) print(d_f) # 2 使用 str 的 startswith contains 等得到的是 bool 的 series,可做条件查询 condition = d_f['course_name'].str.startswith("挖掘机实操") print("22" * 100) print(d_f[condition]) # 3 使用 str 可以进行链式操作 ps:需要注意是的链式操作之间需要使用str属性 # eg:想获取专业名称 d_f.loc[:, "专业名称"] = d_f['course_name'].str.replace('-', '专业名:').str.slice(-5) print("33" * 100) print(d_f)
1111111111111111111111111111111111111111111111111111 course_name 课程名称长度 470 英语-挖 4 471 英语-挖 4 472 英语-挖 4 473 英语-挖 4 474 挖掘机实操-挖 7 475 挖掘机实操-挖 7 476 挖掘机实操-挖 7 477 挖掘机实操-挖 7 478 挖掘机实操-挖 7 479 挖掘机实操-挖 7 2222222222222222222222222222222222222222222222222222 course_name 课程名称长度 474 挖掘机实操-挖 7 475 挖掘机实操-挖 7 476 挖掘机实操-挖 7 477 挖掘机实操-挖 7 478 挖掘机实操-挖 7 479 挖掘机实操-挖 7 3333333333333333333333333333333333333333333333333333 course_name 课程名称长度 专业名称 470 英语-挖 4 专业名:挖 471 英语-挖 4 专业名:挖 472 英语-挖 4 专业名:挖 473 英语-挖 4 专业名:挖 474 挖掘机实操-挖 7 专业名:挖 475 挖掘机实操-挖 7 专业名:挖 476 挖掘机实操-挖 7 专业名:挖 477 挖掘机实操-挖 7 专业名:挖 478 挖掘机实操-挖 7 专业名:挖 479 挖掘机实操-挖 7 专业名:挖
4 使用正则表达式
假设我们有这样一种场景,有两个不同类型的字符串
str_1 = """20106_2022/05/26/19:49:12-19:49:32"""
str_2 = """20_2022-05-26 19:49:12~19:49:32"""
我们需要把格式统一成上面的那种,并获取 编号、日期和开始时间
def format_str_name(str_name): import re re_date = r'(\d{4})[-/]([0,1]?[0-9])?[-/](\d{2})' re_math = r'(\d*)_(\d{4}[/][0,1]?[0-9]?[/]\d{2})/(\d{2}:\d{2}:\d{2})-(\d{2}:\d{2}:\d{2})' f_str_name = re.sub(re_date, r'\1/\2/\3', str_name).replace(' ', '/').replace('~', '-') math_group = re.match(re_math, f_str_name) print(f_str_name, "编号:" + math_group[1], " 日期:" + math_group[2], " 时间:" + math_group[3]) if __name__ == '__main__': str_1 = """20106_2022/05/26/19:49:12-19:49:32""" str_2 = """20_2022-05-26 19:49:12~19:49:32""" format_str_name(str_1) format_str_name(str_2)
def format_str_name_pd(): # pandas 中的 str 自带正则 str_1 = """20106_2022/05/26/19:49:12-19:49:32""" str_2 = """20_2022-05-26 19:49:12~19:49:32""" re_date = r'(\d{4})[-/]([0,1]?[0-9])?[-/](\d{2})' df = pd.Series([str_1, str_2]) df = df.str.replace(re_date, r'\1/\2/\3', regex=True).str.replace(' ', '/').str.replace('~', '-') print(df.str.extract("(\d*)_(\d{4}[/][0,1]?[0-9]?[/]\d{2})/(\d{2}:\d{2}:\d{2})-(\d{2}:\d{2}:\d{2})", expand=False))
0 1 2 3
0 20106 2022/05/26 19:49:12 19:49:32
1 20 2022/05/26 19:49:12 19:49:32
ps:补充python的正则
patten = re.compile('.*v[0-9].[0-9].\d')
if re.match(patten, “目标字符串”):
print("匹配成功")
三、转换函数
Pandas 的数据转换函数 map、apply、applymap
1:map:只用于series,实现每个值-》值的映射
2. apply:用于Series实现每个值的处理,用于Dataframe实现某个轴的Series处理
3:applymap:只用于Dataframe,用于处理该DataFrame的每个元素
1:map函数
-
Series.map(dict)
-
Series.map(function)
def test_map(): """ Series.map(dict) Series.map(function) """ # 获取数据 df = get_data_from_db() data_1 = df[["id", "profession_id", "course_name", "score_total"]].copy() # 方法1:Series.map(dict) data_1.loc[:, "profession_name"] = data_1["profession_id"].map(profession_info_num) print(data_1) """ id profession_id course_name score_total profession_name 0 7 1 语文-经 77.0 经济与管理 1 8 1 语文-经 60.0 经济与管理 2 9 1 语文-经 50.0 经济与管理 3 10 1 语文-经 100.0 经济与管理 4 11 1 语文-经 80.0 经济与管理 .. ... ... ... ... ... 475 482 4 挖掘机实操-挖 60.0 挖掘机 """ # 方法2:Series.map(function) data_1.loc[:, "profession_name2"] = data_1["profession_id"].map(lambda x: profession_info[str(int(x))]) print(data_1) """ id profession_id ... profession_name profession_name2 0 7 1 ... 经济与管理 经济与管理 1 8 1 ... 经济与管理 经济与管理 2 9 1 ... 经济与管理 经济与管理 3 10 1 ... 经济与管理 经济与管理 4 11 1 ... 经济与管理 经济与管理 .. ... ... ... ... ... 475 482 4 ... 挖掘机 挖掘机 """
2:apply函数
- Series.apply(function),函数的参数是每个值
- DataFrame.apply(function),函数的参数是Series
def test_apply(): """ Series.apply(function),函数的参数是每个值 DataFrame.apply(function),函数的参数是Series """ # 获取数据 df = get_data_from_db() data_1 = df[["id", "profession_id", "course_name", "score_total"]].copy() print(data_1) """ id profession_id course_name score_total 0 7 1 语文-经 77.0 1 8 1 语文-经 60.0 .. ... ... ... ... 475 482 4 挖掘机实操-挖 60.0 476 483 4 挖掘机实操-挖 9.0 """ # data_1["profession_id"] 表示是一个Series,可以进行数据类型转换 apply(str) . 和map的用法类似 data_1.loc[:, "profession_name2"] = data_1["profession_id"].apply(str).apply(lambda x: profession_info[x]) # data_1 表示是一个DataFrame。lambda x 的 x 是一个Series,因为指定了 axis=1 所以Series的key是列名,可以用x["profession_id"]获取 data_1.loc[:, "profession_name3"] = data_1.apply(lambda x: profession_info_num[x["profession_id"]], axis=1) print(data_1) """ id profession_id ... profession_name2 profession_name3 0 7 1 ... 经济与管理 经济与管理 1 8 1 ... 经济与管理 经济与管理 .. ... ... ... ... ... 475 482 4 ... 挖掘机 挖掘机 476 483 4 ... 挖掘机 挖掘机 """
3:applymap函数
def test_applymap(): """ DataFrame.applymap(function),用于DataFrame所有值的转换 """ # 获取数据 df = get_data_from_db() data_1 = df[["id", "profession_id", "course_name", "score_total"]].copy() print(data_1.dtypes) """ id int64 profession_id int64 course_name object score_total float64 dtype: object """ data_1.loc[:, ["id", "profession_id", "course_name", "score_total"]] = data_1.applymap(lambda x: str(x)) print(data_1.dtypes) """ id object profession_id object course_name object score_total object dtype: object """
下一篇:饮冰三年-人工智能-Pandas-80-Pandas 数据扩增