pandas入门与进阶(二)

    科技2025-10-31  7

    文章目录

    1. 避免SettingWithCopyWarning报警2. axis参数怎么理解3. 索引相关操作4. 分层索引MultiIndex5. merge:关联多表数据6. concat:实现数据的合并7. 批量拆分或合并excel8. 拆分一列内容变多列9. Pandas的Categorical数据类型可以降低数据存储提升计算速度10. 调整列的顺序11. explode实现一列列表内容变多行12. 复杂多列到多行转换

    1. 避免SettingWithCopyWarning报警

    condition = df["ymd"].str.startswith("2018-03") # 设置温差 # 错误 df[condition]["wen_cha"] = df["bWendu"]-df["yWendu"] # 正确1 df.loc[condition, "wen_cha"] = df["bWendu"]-df["yWendu"] # 正确2 df2 = df[condition].copy() df2["wen_cha"] = df["bWendu"]-df["yWendu"]

    2. axis参数怎么理解

    df = pd.DataFrame( np.arange(12).reshape(3,4), columns=['A', 'B', 'C', 'D'] ) # 代表的就是删除某列 df.drop("A", axis=1) # 代表的就是删除某行 df.drop(1, axis=0) df.mean(axis=0) df.mean(axis=1) # axis=0或者"index": # 如果是单行操作,就指的是某一行 # 如果是聚合操作,指的是跨行cross rows # axis=1或者"columns": # 如果是单列操作,就指的是某一列 # 如果是聚合操作,指的是跨列cross columns 按哪个axis,就是这个axis要动起来(类似被for遍历),另一个axis保持不动,就像梳子

    3. 索引相关操作

    # 设置某列为索引,drop==False,让索引列还保持在column df.set_index("userId", inplace=True, drop=False) # 判断索引是否是递增的 df_shuffle.index.is_monotonic_increasing # 判断索引是否是唯一的,即是否存在重复索引 df_shuffle.index.is_unique # 对索引排序后的数据 df_sorted = df_shuffle.sort_index()

    4. 分层索引MultiIndex

    分层索引:在一个轴向上拥有多个索引层级,可以表达更高维度数据的形式更方便的进行数据筛选,如果有序则性能更好多个key经过groupby等操作的结果是分层索引 Series的分层索引MultiIndex ser = stocks.groupby(['公司', '日期'])['收盘'].mean() ser.index # MultiIndex([('BABA', '2019-10-01'), # ( 'JD', '2019-10-03')], # names=['公司', '日期']) # unstack把二级索引变成列 ser.unstack()

    ser.reset_index() # 多层索引,可以用元组的形式筛选 ser.loc[('BIDU', '2019-10-02')] DataFrame的多层索引MultiIndex stocks.set_index(['公司', '日期'], inplace=True) stocks.index stocks.sort_index(inplace=True) # 筛选数据(注意区别) stocks.loc[('BIDU', '2019-10-02'), :] stocks.loc[['BIDU', 'JD'], :] stocks.loc[(['BIDU', 'JD'], '2019-10-03'), :] # slice(None)代表筛选这一索引的所有内容 stocks.loc[(slice(None), ['2019-10-02', '2019-10-03']), :] stocks.reset_index()

    5. merge:关联多表数据

    Pandas的Merge,相当于Sql的Join,将不同的表按key关联到一个表

    如果left_on和right_on是列表,则可以按照多列相同而合并

    merge的语法:

    pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False, right_index=False, sort=True, suffixes=('_x', '_y'), copy=True, indicator=False, validate=None) left,right:要merge的dataframe或者有name的Serieshow:join类型,‘left’, ‘right’, ‘outer’, ‘inner’(默认)on:join的key,left和right都需要有这个key,相当于left_on和right_on赋值同一个keyleft_on:left的df或者series的keyright_on:right的df或者seires的keyleft_index,right_index:使用index而不是普通的column做joinsuffixes:两个元素的后缀,如果需关联的列有重名,自动添加后缀,默认是(’_x’, ‘_y’) pd.merge(left, right, on='key', suffixes=('_left', '_right')) pd.merge(left, right, left_on='key', right_on='key') 理解left join、right join、inner join、outer join的区别

    6. concat:实现数据的合并

    可以批量多个Pandas对象(DataFrame/Series);给DataFrame添加行;给DataFrame添加列

    concat语法:

    pandas.concat(objs, axis=0, join='outer', ignore_index=False) # objs:一个列表,内容可以是DataFrame或者Series,可以混合 # axis:默认是0代表按行合并,如果等于1代表按列合并 # join:合并的时候索引的对齐方式,默认是outer join,也可以是inner join # ignore_index:是否忽略掉原来的数据索引 # join=inner过滤掉不匹配的列 # 使用axis=1相当于添加新列 # axis=0,默认按行合并数据 pd.concat( [pd.DataFrame([i], columns=['A']) for i in range(5)], ignore_index=True ) # 一行一行的给DataFrame添加数据

    7. 批量拆分或合并excel

    将一个大Excel等份拆成多个Excel # 1. 使用df.iloc方法,将一个大的dataframe,拆分成多个小dataframe # 2. 将使用dataframe.to_excel保存每个小Excel # 计算拆分后的每个excel的行数 user_names = ["xiao_shuai", "xiao_wang", "xiao_ming", "xiao_lei"] # 每个人的任务数目 split_size = total_row_count // len(user_names) if total_row_count % len(user_names) != 0: split_size += 1 # 拆分成多个dataframe df_subs = [] for idx, user_name in enumerate(user_names): # iloc的开始索引 begin = idx*split_size # iloc的结束索引 end = begin+split_size # 实现df按照iloc拆分 df_sub = df_source.iloc[begin:end] # 将每个子df存入列表 df_subs.append((idx, user_name, df_sub)) # 将每个datafame存入excel for idx, user_name, df_sub in df_subs: file_name = f"{splits_dir}/crazyant_blog_articles_{idx}_{user_name}.xlsx" df_sub.to_excel(file_name, index=False) 合并多个小Excel到一个大Excel # 遍历文件夹,得到要合并的Excel名称列表 import os excel_names = [] for excel_name in os.listdir(splits_dir): excel_names.append(excel_name) excel_names # 分别读取到dataframe df_list = [] for excel_name in excel_names: # 读取每个excel到df excel_path = f"{splits_dir}/{excel_name}" df_split = pd.read_excel(excel_path) # 得到username username = excel_name.replace("crazyant_blog_articles_", "").replace(".xlsx", "")[2:] print(excel_name, username) # 给每个df添加1列,即用户名字 df_split["username"] = username df_list.append(df_split) # 使用pd.concat进行合并 df_merged = pd.concat(df_list) # 将合并后的dataframe输出到excel df_merged.to_excel(f"{work_dir}/crazyant_blog_articles_merged.xlsx", index=False)

    8. 拆分一列内容变多列

    def split_func(line): line["姓名"], line["性别"], line["年龄"], line["城市"] = line["数据"].split(":") return line df = df.apply(split_func, axis=1)

    9. Pandas的Categorical数据类型可以降低数据存储提升计算速度

    df.info(memory_usage="deep") # memory usage: 873.4 KB %timeit df.groupby("Gender").size() # 564 µs ± 10.8 µs df_cat["Gender"] = df_cat["Gender"].astype("category") df_cat.info(memory_usage="deep") # memory usage: 513.8 KB %timeit df_cat.groupby("Gender").size() # 324 µs ± 5 µs

    10. 调整列的顺序

    常规方法 df_merge.columns # Index(['班级', '学号', '语文成绩', '姓名', '性别'], dtype='object') # 将'姓名', '性别'两列,放到'学号'的后面 new_columns = df_merge.columns.to_list() # 按逆序insert,会将"姓名","性别"放到"学号"的后面 for name in ["姓名", "性别"][::-1]: new_columns.remove(name) new_columns.insert(new_columns.index("学号")+1, name) new_columns # ['班级', '学号', '姓名', '性别', '语文成绩'] df_merge = df_merge.reindex(columns=new_columns) 自己的方法 # 将Site列插入交换到指定位置 df_sm2_cols = list(df_sm2) df_sm2_cols.insert(0, df_sm2_cols.pop(df_sm2_cols.index('Site'))) df_sm2 = df_sm2.loc[:, df_sm2_cols]

    11. explode实现一列列表内容变多行

    语法:pandas.DataFrame.explode(column) 将dataframe的一个list-like的元素按行复制,index索引随之复制 # 新增一列 df["Genre"] = df["Genres"].map(lambda x:x.split("|")) # Genre的类型是列表 print(df["Genre"][0]) # ['Animation', "Children's", 'Comedy'] print(type(df["Genre"][0])) # <class 'list'> df_new = df.explode("Genre")

    12. 复杂多列到多行转换

    分析:

    一行变多行,可以用explode实现要使用explode,需要先将多列变成一列注意有的列为空,需要做空值过滤 df.columns # ['P/N', 'Description', 'Supplier', 'Supplier PN', 'Supplier.1', 'Supplier PN.1', 'Supplier.2', 'Supplier PN.2'] # 提取待合并的所有列名,一会可以把它们drop掉 merge_names = list(df.loc[:, "Supplier":].columns.values) # ['Supplier', 'Supplier PN', 'Supplier.1', 'Supplier PN.1', 'Supplier.2', 'Supplier PN.2'] def merge_cols(x): """ x是一个行Series,把它们按分隔符合并 """ # 删除为空的列 x = x[x.notna()] # 使用x.values用于合并 y = x.values # 合并后的列表,每个元素是"Supplier" + "Supplier PN"对 result = [] # range的步长为2,目的是每两列做合并 for idx in range(0, len(y), 2): # 使用竖线作为"Supplier" + "Supplier PN"之间的分隔符 result.append(f"{y[idx]}|{y[idx+1]}") # 将所有两两对,用#分割,返回一个大字符串 return "#".join(result) # 添加新列,把待合并的所有列变成一个大字符串 df["merge"] = df.loc[:, "Supplier":].apply(merge_cols, axis=1) # 把不用的列删除掉 df.drop(merge_names, axis=1, inplace=True) df # 最后使用explode把一列变多行 # 先将merge列变成list的形式 df["merge"] = df["merge"].str.split("#") # 执行explode变成多行 df_explode = df.explode("merge") # 把merge列删除掉,得到最终数据 df_explode.drop("merge", axis=1, inplace=True) df_explode # 此外,将一列还原成结果的多列 # 分别从merge中提取两列 df_explode["Supplier"]=df_explode["merge"].str.split("|").str[0] df_explode["Supplier PN"]=df_explode["merge"].str.split("|").str[1] df_explode
    Processed: 0.011, SQL: 8