python:数据预处理 一键实现EXCEL的数据筛选、替换、合并、透视

  • A部分: 数据预处理(占80%工作量)
class yuchuli():
    def __init__(self, *args):
        <blabla> # 引入函数需要的参数
    
    def shanchu(self):     
        # 数据读取部分:
        try:
            df = pd.read_csv('path + sales_file.csv', 
                             encoding='gb18030', low_memory=False)   # gb18030 比 gbk 涵盖的范围广
        except:
            df = pd.read_csv('path + sales_file.csv', 
                             encoding='utf8', low_memory=False)
"""以行或列为对象的操作:"""
        # 列操作 —— 保留需要的字段
        tar_col = ['col1', 'col2']
        df1 = df.loc[:, tar_col]

        #  行操作 —— 去掉多余的行
        df2_1 = df1.dropna(subset=['col2_11', 'col2_12'])           # 删除含有空值的行
        df2_1 = df2_1.drop_duplicates()                             # 删除完全一致的行,保留第一个
        # 等价于
        # df.dropna(subset=['col1', 'col2'], inplace=True)    # 即添加 inplace=True
        # df2_1.drop_duplicates(inplace=True)   

        #  行操作 —— 多条件筛选                                                                                       
        df2_2 = df2_1[(df.col1 != 'value1') & (df2_1['col2'].isin['value2', 'value3'])]    # 筛选 等于某值的行
        # 等价于 (速度没有 isin 稍快, 尤其是条件值变多的时候。但是3者性能几乎一致。)
        # df2_2 = df2_1[(df.Col2_21 != 'value1') & ((df.Col2_22 == 'value2')| (df.Col2_22 == 'value3']))]
        # df2_2 = df2_1.loc[(df.Col2_21 != 'value1') & (df.Col2_22.isin['value2', 'value3'])]
"""以 行数据 为对象的操作:"""
        # 预处理之 —— 统一大小写和标点符号空格等
        df2_2['customer_name'] = df2_2['customer_name'].str.lower()     # 处理英文大小写问题
        df2_2.replace({'customer_name': [r'(', r')', r' ']},          # 统一标点符号和空格
                      {'customer_name': ['(', ')', '']}, 
                      regex=True, inplace=True)
        # 对整个df进行替换
        # df2_2.replace([r'(', r')', r' '],  
        #               ['(', ')', ''], 
        #               regex=True, inplace=True) 

        # 预处理之 —— 设计不同字段的值替换 & 生成新字段
        mask1= df2_2['col_1'] == 'value1'
        mask2 = df2_2['col_2'] == 'value2'
        df2_2['col_new'] = np.select([mask1, mask2], ['value1_new', 'value2_new'], default=0)
        # 等价于
        # df2_2.loc[(df2_2['col_1'] == 'value1'), 'col_new'] = 'value1_new'
        # df2_2.loc[(df2_2['col_2'] == 'value1'), 'col_new'] = 'value2_new'
        # df2_2.loc[(df2_2['col_new'] != 'value1_new') & (df2_2['col_new'] != 'value2_new'), 'col_new'] = 0
        
        # 预处理之 —— 涉及不同字段的值替换
        mask1= df2_2['col_1'] == 'value1'
        mask2 = df2_2['col_2'] == 'value2'
        df2_2['col_3'] = np.select([mask1 | mask2], ['value_new'],
                                   default=df2_2['col_3'])     # 多条件可以使用"and"("&")、"or"("| ")、“~mask”(非)
        # 等价于
        # df2_2.loc[(df2_2['col_1'] == 'value1'), 'col_3'] = 'value1_new'
        # df2_2.loc[(df2_2['col_2'] == 'value1'), 'col_3'] = 'value2_new'
        
        # 预处理之 —— 1个字段的值替换
        df2_2.replace({'col1': [r'.*key_word1.*', 'value1']}, 'value_new', inplace=True)
        
        # 预处理之 —— 字段重命名
        df2_2.rename(columns={'col1_name': 'col1_name_new',
                              'col2_name': 'col2_name_new'}, inplace=True}
                  
        
        return df2_2
  • df.col等价于df['col'],不同在于df['col.a']可以指明df中名为col.a的列,前者不可以。
  • 更多关于str.replace()的信息, 可参考string.replace vs re.sub以及反向选择替换
  • df_hangye.drop_duplicates(inplace=True)
    – 假设表df1和表df2在公共字段中各有M、N个相同的值,使用df1.merge(df2, on='col')之后会有M*N重复记录

  • B部分: 数据透视
from datetime import datetime, timedelta


def toushibiao():
    try:
        df = pd.concat([df1, df2], axis=0, how='outer', )
        
        yesterday = datetime.today() - timedelta(1)             # 昨天的日期。datetime.date不可以用于和datetime类型的作比较
        target_day = yesterday.replace(year=yesterday.year-1)   # 去年昨天的日期       
        df['col_time'] = pd.to_datetime(df['col_time'])         # 转化为datetime类型
        df_new = df[df['col_time'] <= target_day]               # 获取指定日期之前的数据        

        pivot_table = pd_new.pivot_table(df_new,
                                         values= [col OR col_list],
                                         columns=[col OR col_list],
                                         index= [col OR col_list],
                                         aggfunc=np.sum)        # 做数据透视表
                                     
        piv_tab.columns = pivot_table.columns.droplevel(0)       # 表头扁平化,具体见下边附的链接。
        pivot_table = pivot_table_1.rename_axis(None, axis=1).reset_index()      # 表头扁平化,具体见下边负的链接。
        pivot_table_1.to_csv('文件路径+pivot_table_1.csv', encoding='gbk')        # 保存透视结果到本地计算机
    except:
        print('没有找到文件"path + sales_of_xiaohua.csv"。')        

获取前一天的日期

from datetime import date, timedelta
    yesterday = date.today() - timedelta(1)
    print(yesterday.strftime(%Y%m%d))

注:更多关于表头扁平化的信息,可参考多维透视表 - 表头扁平化输出


  • C部分:合并多个透视表&保存
try:
    # 合并多个表
    merged_table = pivot_table1.merge(pivot_table2, on=['col_mutual'], how='outer)
    
    # 把小数更改为百分比
    merged_table['new_column_float'] = merged_table['column_1'] / merged_table['column_1']
    merged_table['new_column_percent'] = pd.Series(['{:.2f}%'.format(val * 100) for val in merged_table['new_column_float']], 
                                                   index=merged_table.index)
    
    # 保存最终数据                                                 
    merged_table.to_csv('path+filename.csv', encoding='gb18030', index=False)

except:
    print('没有合并生成XXX文件。')

注:

  • 更多关于 merge(),join(), concat()的信息,可参考《Merge, join, and concatenate》的特点和区别
  • if-elif-else可以和try-except组合使用。

你可能感兴趣的:(python,可视化,案例)