Python基础|【Pandas】Pandas中的DataFrame数据结构的部分用法

?由于最近涉及到数据分析,所以使用了很多关于pandas包的一些功能,持续总结如下:

文章目录

      • 01. 读写数据
        • 1.1 读取mysql中数据转DataFrame格式
        • 1.2 读取多个csv文件合并到同一个DataFrame中
        • 1.3 从DataFrame中读取行列
        • 1.4 遍历DataFrame
      • 02.统计方法
        • 2.1 统计个数
        • 2.2 分组求和
        • 2.3 根据其他列计算出新列的值
        • 2.4 统计每行特定值的个数
        • 2.5 关联
        • 2.6 分组取topN
      • 03.其他
        • 3.1 类型转换
        • 3.2 排序然后重新编号
        • 3.3 查找和替换
        • 3.4 填充缺失时间
        • 3.5 修改列名
        • 3.6 去重
        • 3.7 索引和列的相互转换
        • 3.8 行转为列
      • 04.计算
        • 4.1 前后行相减

01. 读写数据
1.1 读取mysql中数据转DataFrame格式
select_sql = """select * from sku_params_parsed order by product_time""" results = db_client.commit_with_sql(select_sql) column_names = ["spu", "sku_name", "is5G", "price", "battery", "thickness", "screen_size", "ram", "rom", "weight", "screen_refresh"] df = pd.DataFrame( [[temp[2], temp[1], temp[17], temp[3],temp[8], temp[9], temp[10], temp[11], temp[12], temp[13], temp[14]] for temp in results], columns=column_names)

1.2 读取多个csv文件合并到同一个DataFrame中
header = [ "cat_lvl5_name", "goods_name", "goods_id", "sale_channel_2", "sale_channel_name_2", "pay_cnt", "signed_cnt", "srv_return_cnt", "offline_return_cnt" ] df_from_each_file = [] for home, _, files in os.walk(CURRENT_PATH + "/SalesData/1"): for filename in files: full_name = os.path.join(home, filename) # 读取csv文件 temp_df = pd.read_csv(full_name, header=None) # 增加header temp_df.columns = header # 获取df的行数 row = temp_df.shape[0] # 增加一列 now = time.strftime("%Y-%m-%d", time.strptime(filename.replace(".csv", ""), "%Y%m%d")) temp_df['date'] = [now] * row df_from_each_file.append(temp_df)# 多个csv文件读取后得到的dataframe进行合并 concatenated_df = pd.concat(df_from_each_file, ignore_index=True)

1.3 从DataFrame中读取行列
# loc,基于列label,可选取特定行(根据行index); # iloc,基于行/列的序号;# 读取指定列名的多列 df[['a', 'b', 'c']]# 读取指定列号的多列,读取所有行的第2列到第20列 df.iloc[:, 2:20] # 读取指定列名的,所有行 df.loc[:, ["a", "b"]]# 读取指定行号的数据,读取所有猎的第2行到第20行的数据 df.iloc[2:20, :] # 读取指定行号的指定列名的数据 df.loc[2:20, ['a', 'b']]#取p_feature中不包含列名为index 的所有列 p_feature = p_feature.iloc[:, p_feature.columns != "index"] # 包含 p_feature = p_feature.loc[:,p_feature.columns.isin(["index","授信编号"])] # 加~ 变为不包含 p_feature = p_feature.loc[:,~p_feature.columns.isin(["index","授信编号"])]

1.4 遍历DataFrame
import pandas as pd #读入数据 df = pd.read_table('d:/Users/chen_lib/Desktop/tmp.csv',sep=',', header='infer') df.head() -----------------result------------------ maseffectdatenum 0 371379 2019-07-15 361 1 344985 2019-07-13 77 2 425090 2019-07-01 105 3 344983 2019-02-19 339 4 432430 2019-02-21 162

# 方法一: for index, row in df.iterrows(): print(index,row['mas'],row['num']) ------------result--------------- 0 371379 361 1 344985 77 2 425090 105 3 344983 339 4 432430 162# 方法二 for row in df.itertuples(): print(getattr(row, 'mas'), getattr(row, 'num')) # 输出每一行 -------------result----------------- 371379 361 344985 77 425090 105 344983 339 432430 162# 方法三: for index, row in df.iteritems(): print(index,row[0],row[1],row[2]) -------------result------------------ masterhotelid 371379 344985 425090 effectdate 2019-07-15 2019-07-13 2019-07-01 quantity 361 77 105

02.统计方法
2.1 统计个数
# 统计各类出现的次数, 结果是 Series 格式,可以直接利用dict转换为字典形式 counts=df.value_counts() print(counts) # 统计个数大于1的行数 print(counts[counts>1])# 统计符合某个范围的值的个数 # 注意这里不能使用and和or, 对应的应该使用 & 和 | df[(df["price"]>999) & (df["price"]<=1499)]["price"].count() # 结果的类型是 numpy.int64,需要利用int强制转换为int类型

2.2 分组求和
# 根据date和sale_channel_name_2进行分组,然后对其他字段分别使用不同的聚合函数 # 由于group by 之后 分组依据会变成index,在保存的时候不会保存到excel,所以通过reset_index # 重新进行index的划分 import numpy as np tm_df = concatenated_df[concatenated_df["sale_channel_name_2"] == "天猫淘宝直营"].groupby( ['date', 'sale_channel_name_2'] ).agg({'goods_id': np.max, 'sale_channel_2': np.max, "pay_cnt":np.sum, "signed_cnt":np.sum, "srv_return_cnt":np.sum, "offline_return_cnt":np.sum}).reset_index()

2.3 根据其他列计算出新列的值
# 根据signed_cnt、srv_return_cnt、offline_return_cnt三列的值计算出real_sales的值 # 主要依赖于 lambda 的匿名函数 # axis = 1,就会把一行数据作为Series的数据结构传入给自己实现的函数中, # 我们在函数中实现对Series不同属性之间的计算,返回一个结果 tm_df["real_sales"] = tm_df.apply( lambda x: int(x.signed_cnt) - int(x.srv_return_cnt) - int(x.offline_return_cnt), axis = 1 )

2.4 统计每行特定值的个数
# 返回每行缺失值的总数 df.isnull().sum(axis=1)# 返回每列缺失值的总数 df.isnull().sum(axis=0)# 返回每行指定值的个数 active_30day_train_df['active_num'] = (active_30day_train_df == True).sum(axis=1)

2.5 关联
# how的方法有: left、right、outer、inner分别表示 # 只保留左表的所有数据、只保留右表的所有数据、保留两个表的所有信息、只保留两个表中公共部分的信息 result = pd.merge(left, right, how='left', on=['key1', 'key2'])# 如果和表合并的过程中遇到有一列两个表都同名,但是值不同,合并的时候又都想保留下来,就可以用suffixes给每个表的重复列名增加后缀。 result = pd.merge(left, right, on='k', suffixes=['_l', '_r'])

2.6 分组取topN
# 整体思路是将分组标准转化为索引,然后利用head函数即可 # 直接取索引的topN如下 df.groupby("category").head(10) # 先分组再取topN如下 count_with_category = df.groupby(["category", "tag_name"]).agg( {"count_num": np.sum} ).sort_values(by=["category", "count_num"], ascending=[False, False]).groupby("category").head(10)

03.其他
3.1 类型转换
# DataFrame一列统一转换为int类型 df['price'] = df['price'].apply(int) # DataFrame一列先替换某些字符串后再统一转换为int类型 df['battery'] = df['battery'].str.replace("mAh", "").apply(int) # 同时转换多列为数值型 data_df[["闪存", "内存", "价格", "厚度", "重量"]] = data_df[ ["闪存", "内存", "价格", "厚度", "重量"] ].apply(pd.to_numeric)

3.2 排序然后重新编号
# 设置drop=True可以不保留原有的index列 concatenated_df = concatenated_df .sort_values(['date', 'sale_channel_name_2'], ascending=[True, False]) .reset_index(drop=True)

3.3 查找和替换
# 查找sku_id列满足某个条件,然后替换source列为某个值 temp_df.loc[temp_df['sku_id'].str.contains('-'), 'source'] = 'tianmao' # 查找sku_id列不满足某个条件,然后替换source列为某个值 temp_df.loc[~temp_df['sku_id'].str.contains('-'), 'source'] = 'tianmao'# 查找concatenated_df的commentCount列中包含+的,nan用false代替 concatenated_df[concatenated_df["commentCount"].str.contains('\\+', na=False)]# 替换某列(数字和字符串混合的列)中字符换中的+号,且保证不存在nan mask = concatenated_df['commentCount'].apply(type) == str concatenated_df['commentCount'] = concatenated_df['commentCount'].mask( mask, concatenated_df['commentCount'].str.replace("+", "") )

3.4 填充缺失时间
# 日期列转换为pandas的日期格式 temp_df['date'] = pd.to_datetime(temp_df["date"]) # 设置dataframe的索引为date df_date = temp_df.set_index("date") df_date = df_date.set_index(pd.to_datetime(df_date.index)) # 获取日期列的最小时间和最大时间, Timestamp格式 max_date = df['date'].max() min_date = df['date'].min() # 生成完整的日期序列 pdates = pd.date_range(start=min_date, end=max_date) # 填充缺失索引,并填充默认值 df_date_new = df_date.reindex(pdates, fill_value=https://www.it610.com/article/0)

3.5 修改列名
# 修改列名a,b为A、B。 df.columns = ['A','B']# 只修改列名a为A df.rename(columns={'a':'A'})

3.6 去重
# 根据某一列去重 concatenated_df.drop_duplicates(['goods_name'])

3.7 索引和列的相互转换
df.set_index('date', inplace=True) # column 改为 index df.reset_index() # (all)index 改为 column

3.8 行转为列 【Python基础|【Pandas】Pandas中的DataFrame数据结构的部分用法】参考地址:https://www.cnblogs.com/traditional/p/11967360.html
print(df) """ 姓名科目分数 0古明地觉语文90 1古明地觉数学95 2古明地觉英语96 3芙兰朵露语文87 4芙兰朵露数学92 5芙兰朵露英语98 6琪露诺语文100 7琪露诺数学9 8琪露诺英语91 """# 注意此处也可以多级索引,用LIST形式,例如 index=["班级", "姓名"] print(pd.pivot(df, index="姓名", columns="科目", values="分数")) """ 科目数学英语语文 姓名 古明地觉959690 琪露诺991100 芙兰朵露929887 """ # 可以看到上面这一步,就直接相当于df.set_index(["姓名", "科目"])["分数"].unstack() # 然后再手动rename_axis、再reset_index即可 # 可以通过 rename_axis(index=, columns=) 来给坐标轴重命名 new_df = new_df.rename_axis(columns=None) new_df = new_df.reset_index() print(new_df) """ 姓名数学英语语文 0古明地觉959690 1琪露诺991100 2芙兰朵露929887 """# 如果我们是想将"姓名"变成列的话, 那么就指定columns="姓名"即可 print(pd.pivot(df, index="科目", columns="姓名", values="分数")) """ 姓名古明地觉琪露诺芙兰朵露 科目 数学95992 英语969198 语文9010087 """

04.计算
4.1 前后行相减
# 由于第一行是没有前一行的,所以一般需要跟 .fillna(0) 将第一行的结果转换为数字 df["daily_comment"] = (df["commentCount"] - df["commentCount"].shift(1)).fillna(0)

    推荐阅读