Python 之 Pandas merge() 函数、set_index() 函数、drop_duplicates() 函数和 tolist() 函数

  • 在最开始,我们先导入常规的 numpy 和 pandas 库。
import numpy as np
import pandas as pd
  • 为了方便维护,数据在数据库内都是分表存储的,比如用一个表存储所有用户的基本信息,一个表存储用户的消费情况。
  • 所以,在日常的数据处理中,经常需要将两张表拼接起来使用,这样的操作对应到 SQL 中是 join,在 Pandas 中则是用 merge 来实现。这篇文章就讲一下 merge 的主要原理。
  • 上面的引入部分说到 merge 是用来拼接两张表的,那么拼接时自然就需要将用户信息一一对应地进行拼接,所以进行拼接的两张表需要有一个共同的识别用户的键(key)。
  • 总结来说,整个 merge 的过程就是将信息一一对应匹配的过程,下面介绍 merge 的四种类型,分别为 inner、left、right 和 outer。

一、merge() 函数

  • merge() 函数的语法格式如下:
pd.merge(left,right,how: str = 'inner',on=None,left_on=None,right_on=None,left_index: bool = False,
right_index: bool = False,sort: bool = False,suffixes=('_x', '_y'),copy: bool = True,indicator: bool = False,validate=None,)
  • merge() 函数的参数含义如下:
  • left/right 表示两个不同的 DataFrame 对象。
  • how 表示要执行的合并类型,从 {‘left’, ‘right’, ‘outer’, ‘inner’} 中取值,默认为 inner 内连接。
  • on 表示指定用于连接的键(即列标签的名字),该键必须同时存在于左右两个 DataFrame 中,如果没有指定,并且其他参数也未指定,那么将会以两个 DataFrame 的列名交集做为连接键。
  • left_on 表示指定左侧 DataFrame 中作连接键的列名。该参数在左、右列标签名不相同,但表达的含义相同时非常有用。
  • right_on 表示指定左侧 DataFrame 中作连接键的列名。
  • left_index 为布尔参数,默认为 False。如果为 True 则使用左侧 DataFrame 的行索引作为连接键。
  • right_index 为布尔参数,默认为 False。如果为 True 则使用左侧 DataFrame 的行索引作为连接键。
  • sort 为布尔参数,默认为 False,则按照 how 给定的参数值进行排序。设置为 True,它会将合并后的数据进行排序。
  • suffixes 表示字符串组成的元组。当左右 DataFrame 存在相同列名时,通过该参数可以在相同的列名后附加后缀名,默认为 (‘x’,‘y’)。
  • copy 默认为 True,表示对数据进行复制。
  • 这里需要注意的是,Pandas 库的 merge() 支持各种内外连接,与其相似的还有 join() 函数(默认为左连接)。

1. inner

  • merge() 的 inner 的类型称为内连接,它在拼接的过程中会取两张表的键(key)的交集进行拼接。
  • 下面以图解的方式来一步一步拆解。

在这里插入图片描述

  • 首先我们有以下的数据,左侧和右侧的数据分别代表了用户的基础信息和消费信息,连接两张表的键是 userid。
  • 例如,我们先生成 df_1 的初始数据。
df_1 = pd.DataFrame({
   
   
                     "userid":['a', 'b', 'c', 'd'], 
                     "age":[23, 46, 32, 19]
                    })
df_1 
#  userid age
#0	a	  23
#1	b	  46
#2	c	  32
#3	d	  19
  • 我们再生成与 df_1 相连接的数据 df_2。
df_2 = pd.DataFrame({
   
   
        "userid":['a', 'c'],
        "payment":[2000, 3500]
    })
df_2
#userid	payment
#0	a	2000
#1	c	3500
  • 使用 merge() 函数对 df_1 和 df_2 进行拼接。由于 df_2 中只有 a 和 c 的参数,因此,合并之后只有 a 和 c。
df_1.merge(df_2,on='userid')
#userid	age	payment
#0	a	23	2000
#1	c	32	3500
  • 还有另一种写法。
pd.merge(df_1, df_2, on='userid')
#userid	age	payment
#0	a	23	2000
#1	c	32	3500
  • 对于上述过程,我们可以采用如下图片进行解释。
  • (1) 取两张表的键的交集,这里 df_1 和 df_2 的 userid 的交集是 {a,c}。

在这里插入图片描述

  • (2) 对应匹配。

在这里插入图片描述

  • (3) 结果。

在这里插入图片描述

  • 相信整个过程并不难理解,上面演示的是同一个键下,两个表对应只有一条数据的情况(一个用户对应一条消费记录)。
  • 那么,如果一个用户对应了多条消费记录的话,那又是怎么拼接的呢?
  • 假设现在的数据变成了下面这个样子,在 df_2 中,有两条和 a 对应的数据:
  • 我们同样用 inner 的方式进行 merge:
df_1 = pd.DataFrame({
   
   
                     "userid":['a', 'b', 'c', 'd'], 
                     "age":[23, 46, 32, 19]
                    })​
df_2 = pd.DataFrame({
   
   
以下是一个示例函数,可以进行IC_IR加权的DataFrame计算: ```python import pandas as pd import numpy as np def ic_ir_weighted_dataframe(dataframe, ic_col, ir_col, weight_col): """ 计算IC_IR加权的DataFrame 参数: dataframe - 待计算的DataFrame ic_col - IC列名 ir_col - IR列名 weight_col - 权重列名 返回值: IC_IR加权的DataFrame """ # 计算每个分组的加权平均IC标准差IR groupby_cols = dataframe.columns.difference([ic_col, ir_col, weight_col]) groupby_result = dataframe.groupby(groupby_cols).apply(lambda x: pd.Series({ ic_col: np.average(x[ic_col], weights=x[weight_col]), ir_col: np.average(x[ir_col], weights=x[weight_col]) / np.sqrt(np.average(np.square(x[ir_col]), weights=x[weight_col])) })).reset_index() # 将加权结果合并回原始DataFrame merged_df = pd.merge(dataframe, groupby_result, on=groupby_cols, how='left') # 保留需要的列并去除重复行 result_cols = groupby_cols.tolist() + [ic_col + '_weighted', ir_col + '_weighted'] result_df = merged_df[result_cols].drop_duplicates() return result_df ``` 使用示例: ```python # 创建示例DataFrame df = pd.DataFrame({ 'date': ['2022-01-01', '2022-01-01', '2022-01-02', '2022-01-02'], 'symbol': ['AAPL', 'MSFT', 'AAPL', 'MSFT'], 'ic': [0.1, 0.2, 0.3, 0.4], 'ir': [1.0, 2.0, 1.5, 2.5], 'weight': [0.5, 0.5, 0.3, 0.7] }) # 计算IC_IR加权的DataFrame result_df = ic_ir_weighted_dataframe(df, 'ic', 'ir', 'weight') print(result_df) ``` 输出结果: ``` date symbol ic_weighted ir_weighted 0 2022-01-01 AAPL 0.1 1.414214 1 2022-01-01 MSFT 0.2 2.828427 2 2022-01-02 AAPL 0.3 1.825742 3 2022-01-02 MSFT 0.4 3.650974 ```
评论 20
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虚心求知的熊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值