python pandas dataframe 合并_Python 基础 | pandas 中 dataframe 的整合与形变 (merge & reshape)...

Python 基础 | pandas 中 dataframe 的整合与形变 (merge & reshape)

目录

行的 unionpd.concat

df.append

列的 joinpd.concat

pd.merge

df.join

行列转置pivot

stack&unstack

melt

本文示例数据下载 https://pan.baidu.com/s/1lQIpvwThXRkUJ16Fl4ERNA , 密码: vwy3importpandasaspd

# 数据是之前在 cnblog 上抓取的部分文章信息

df=pd.read_csv('./data/SQL 测试用数据_20200325.csv',encoding='utf-8')

# 为了后续演示, 抽样生成两个数据集

df1=df.sample(n=500,random_state=123)

df2=df.sample(n=600,random_state=234)

# 保证有较多的交集

# 比例抽样是有顺序的, 不加 random_state, 那么两个数据集是一样的

行的 union

pandas 官方教程

pd.concat

pd.concat 主要参数说明:

要合并的 dataframe, 可以用 [] 进行包裹, e.g. [df1,df2,df3];

axis=0,axis 是拼接的方向, 0 代表行, 1 代表列, 不过很少用 pd.concat 来做列的 join

join='outer'

ignore_index: bool = False, 看是否需要重置 index

如果要达到 union all 的效果, 那么要拼接的多个 dataframe, 必须:

列名名称及顺序都需要保持一致

每列的数据类型要对应

如果列名不一致就会产生新的列

如果数据类型不一致, 不一定报错, 要看具体的兼容场景

df2.columns

输出:Index(['href','title','create_time','read_cnt','blog_name','date','weekday','hour'],dtype='object')

# 这里故意修改下第 2 列的名称

df2.columns=['href','title_2','create_time','read_cnt','blog_name','date','weekday','hour']

print(df1.shape,df2.shape)

# inner 方法将无法配对的列删除

# 拼接的方向, 默认是就行(axis=0)

df_m=pd.concat([df1,df2],axis=0,join='inner')

print(df_m.shape)

输出:(500,8)(600,8)

(1100,7)

# 查看去重后的数据集大小

df_m.drop_duplicates(subset='href').shape

输出:(849,7)

df.append

和 pd.concat 方法的区别:

append 只能做行的 union

append 方法是 outer join

相同点:

append 可以支持多个 dataframe 的 union

append 大致等同于pd.concat([df1,df2],axis=0,join='outer')

df1.append(df2).shape

输出:(1100,9)

df1.append([df2,df2]).shape

输出:

(1700, 9)

列的 join

pd.concat

pd.concat 也可以做 join, 不过关联的字段不是列的值, 而是 index

也因为是基于 index 的关联, 所以 pd.concat 可以对超过 2 个以上的 dataframe 做 join 操作# 按列拼接, 设置 axis=1

# inner join

print(df1.shape,df2.shape)

df_m_c=pd.concat([df1,df2],axis=1,join='inner')

print(df_m_c.shape)

输出:(500,8)(600,8)

(251,16)

这里是 251 行, 可以取两个 dataframe 的 index 然后求交集看下set1=set(df1.index)

set2=set(df2.index)

set_join=set1.intersection(set2)

print(len(set1),len(set2),len(set_join))

输出:500600251

pd.merge

pd.merge 主要参数说明:

left, join 操作左侧的那一个 dataframe

right, join 操作左侧的那一个 dataframe, merge 方法只能对 2 个 dataframe 做 join

how: join 方式, 默认是 inner,str = 'inner'

on=None 关联的字段, 如果两个 dataframe 关联字段一样时, 设置 on 就行, 不用管 left_on,right_on

left_on=None 左表的关联字段

right_on=None 右表的关联字段, 如果两个 dataframe 关联字段名称不一样的时候就设置左右字段

suffixes=('_x', '_y'), join 后给左右表字段加的前缀, 除关联字段外print(df1.shape,df2.shape)

df_m=pd.merge(left=df1,right=df2\

,how='inner'\

,on=['href','blog_name']

)

print(df_m.shape)

输出:(500,8)(600,8)

(251,14)

print(df1.shape,df2.shape)

df_m=pd.merge(left=df1,right=df2\

,how='inner'\

,left_on='href',right_on='href'

)

print(df_m.shape)

输出:(500,8)(600,8)

(251,15)

# 对比下不同 join 模式的区别

print(df1.shape,df2.shape)

# inner join

df_inner=pd.merge(left=df1,right=df2\

,how='inner'\

,on=['href','blog_name']

)

# full outer join

df_full_outer=pd.merge(left=df1,right=df2\

,how='outer'\

,on=['href','blog_name']

)

# left outer join

df_left_outer=pd.merge(left=df1,right=df2\

,how='left'\

,on=['href','blog_name']

)

# right outer join

df_right_outer=pd.merge(left=df1,right=df2\

,how='right'\

,on=['href','blog_name']

)

print('inner join 左表∩右表:'+str(df_inner.shape))

print('full outer join 左表∪右表:'+str(df_full_outer.shape))

print('left outer join 左表包含右表:'+str(df_left_outer.shape))

print('right outer join 右表包含左表:'+str(df_right_outer.shape))

输出:

(500, 8) (600, 8)

inner join 左表∩右表:(251, 14)

full outer join 左表∪右表:(849, 14)

left outer join 左表包含右表:(500, 14)

right outer join 右表包含左表:(600, 14)

df.join

df.join 主要参数说明:

other 右表

on 关联字段, 这个和 pd.concat 做列 join 一样, 是关联 index 的

how='left'

lsuffix='' 左表后缀

rsuffix='' 右表后缀print(df1.shape,df2.shape)

df_m=df1.join(df2,how='inner',lsuffix='1',rsuffix='2')

df_m.shape

输出:(500,8)(600,8)

(251,16)

行列转置

pandas 官方教程# 数据准备

importmath

df['time_mark']=df['hour'].apply(lambdax:math.ceil(int(x)/8))

df_stat_raw=df.pivot_table(values=['read_cnt','href']\

,index=['weekday','time_mark']\

,aggfunc={'read_cnt':'sum','href':'count'})

df_stat=df_stat_raw.reset_index()

df_stat.head(3)

如上所示, df_stat 是两个维度 weekday,time_mark

以及两个计量指标 href, read_cnt

pivot

c1.gif# pivot 操作中, index 和 columns 都是维度

res=df_stat.pivot(index='weekday',columns='time_mark',values='href').reset_index(drop=True)

res

stack&unstack

stack 则是将层级最低 (默认) 的 column 转化为 index

unstack 默认是将排位最靠后的 index 转成 column(column 放到下面)

c1.gif

c1.gif

c1.gif# pandas.pivot_table 生成的结果如下

df_stat_raw

# unstack 默认是将排位最靠后的 index 转成 column(column 放到下面)

df_stat_raw.unstack()

# unstack 也可以指定 index, 然后转成最底层的 column

df_stat_raw.unstack('weekday')

# 这个语句的效果是一样的, 可以指定 `index` 的位置

# stat_raw.unstack(0)

# stack 则是将层级醉倒的 column 转化为 index

df_stat_raw.unstack().stack().head(5)

# 经过两次 stack 后就成为多维表了

# 每次 stack 都会像洋葱一样将 column 放到左侧的 index 来(放到 index 序列最后)

df_stat_raw.unstack().stack().stack().head(5)

输出:weekday time_mark

10href4

read_cnt2386

1href32

read_cnt31888

2href94

dtype:int64

pd.DataFrame(df_stat_raw.unstack().stack().stack()).reset_index().head(5)

c1.gif

melt

melt 方法中 id_vals 是指保留哪些作为维度(index), 剩下的都看做是数值(value)

除此之外, 会另外生成一个维度叫 variable, 列转行后记录被转的的变量名称

c1.gifprint(df_stat.head(5))

df_stat.melt(id_vars=['weekday']).head(5)

df_stat.melt(id_vars=['weekday','time_mark']).head(5)

来源: https://www.cnblogs.com/dataxon/p/12634897.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值