饮冰三年-人工智能-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())
series&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())
dataframe&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 的字符串处理:官网

  1. 使用方法:先获取 Series  str 属性,然后再在属性上调用函数
  2. 只能在字符串列上使用
    • 否则会报错 AttributeError: Can only use .str accessor with string values!
  3. 只能在series上使用,DataFrame上没有str属性和处理方法
  4. 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)
python中使用正则方式
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))
pandas中使用正则表达式
       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函数

  1. Series.map(dict)

  2. 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  ...             挖掘机               挖掘机
    """
map函数

2:apply函数

  1. Series.apply(function),函数的参数是每个值
  2. 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  ...              挖掘机               挖掘机
    """
apply函数

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
    """
applymap函数

 



下一篇:饮冰三年-人工智能-Pandas-80-Pandas 数据扩增
posted @ 2022-09-03 15:36  逍遥小天狼  阅读(53)  评论(0编辑  收藏  举报