详解Pandas如何高效对比处理DataFrame的两列数据

目录
  • 楔子
  • combine_first
  • combine
  • update

楔子

我们在用 pandas 处理数据的时候,经常会遇到用其中一列数据替换另一列数据的场景。比如 A 列和 B 列,对 A 列中不为空的数据不作处理,对 A 列中为空的数据使用 B 列对应索引的数据进行替换。这一类的需求估计很多人都遇到,当然还有其它更复杂的。

解决这类需求的办法有很多,这里我们来推荐几个。

combine_first

这个方法是专门用来针对空值处理的,我们来看一下用法。

import pandas as pd

df = pd.DataFrame(
    {"A": ["001", None, "003", None, "005"],
     "B": ["1", "2", "3", "4", "5"]}
)
print(df)
"""
      A  B
0   001  1
1  None  2
2   003  3
3  None  4
4   005  5
"""

# 我们现在需求如下,如果 A 列中的数据不为空,那么不做处理
# 如果为空,则用 B 列中对应的数据进行替换
df["A"] = df["A"].combine_first(df["B"])
print(df)
"""
     A  B
0  001  1
1    2  2
2  003  3
3    4  4
4  005  5
"""

使用方法很简单,首先是两个 Series 对象,假设叫 s1 和 s2,那么 s1.combine_first(s2) 就表示用 s2 替换掉 s1 中为空的数据。如果 s1 和 s2 的某个相同索引对应的数据都是空,那么结果只能是空。当然这个方法不是在原地操作,而是会返回一个新的 Series 对象。

另外这个方法的理想前提是两个 Series 对象的索引是一致的,因为替换是根据索引来指定位置的,举个例子。

import pandas as pd

s1 = pd.Series(["001", None, None, "004"], 
               index=['a', 'b', 'c', 'd'])
s2 = pd.Series(["2", "3", "4"], 
               index=['b', 'd', "e"])

print(s1)
"""
a     001
b    None
c    None
d     004
dtype: object
"""
print(s2)
"""
b    2
d    3
e    4
dtype: object
"""

print(s1.combine_first(s2))
"""
a    001
b      2
c    NaN
d    004
e      4
dtype: object
"""

解释一下,首先替换的都是 s1 中值为空的数据,如果不为空那么不做任何处理。s1 中值为空的数据有两个,索引分别为 b、c,那么会用 s2 中索引为 b、c 的数据进行替换。但 s2 中只存在索引为 b、不存在索引为 c 的数据,那么就只能替换一个值。

另外我们看到结尾还多了个索引为 e 的数据,是的,如果 s2 中的数据,s1 没有,那么会直接加上去。

注意:pandas 的很多操作都是基于自带的索引进行的,并不是简单的从上往下一一对应。即便是很多 pandas 老手,偶尔也会犯这个错误。

当然大部分情况下我们处理的都是同一个 DataFrame 的两列,对于同一个 DataFrame 中的两列,它们的索引显然是一致的,所以就是简单的从上到下,不会有太多花里胡哨的。

combine

combine 和 combine_first 类似,只是需要指定一个函数。

import pandas as pd

df = pd.DataFrame(
    {"A": ["001", None, "003", None, "005"],
     "B": ["1", "2", "3", "4", "5"]}
)
print(df)
"""
      A  B
0   001  1
1  None  2
2   003  3
3  None  4
4   005  5
"""

df["A"] = df["A"].combine(df["B"], 
                          lambda a, b: a if pd.notna(a) else b)
print(df)
"""
     A  B
0  001  1
1    2  2
2  003  3
3    4  4
4  005  5
"""

我们指定了一个匿名函数,参数 a、b 就代表 df["A"] 和 df["B"] 中对应的每一个数据。如果 a 不为空,那么返回 a,否则返回 b。

所以我们使用 combine 实现了 combine_first 的功能,combine_first 是专门对空值进行替换的,但 combine 则是可以让我们自己指定逻辑。我们可以实现 combine_first 的功能,也可以实现其它的功能。

import pandas as pd

s1 = pd.Series([1, 22, 3, 44])
s2 = pd.Series([11, 2, 33, 4])

# 哪个元素大就保留哪一个
print(s1.combine(s2, lambda a, b: a if a > b else b))
"""
0    11
1    22
2    33
3    44
dtype: int64
"""

# 两个元素进行相乘
# 当然,对于目前这个需求,最好的办法是 s1 * s2
print(s1.combine(s2, lambda a, b: a * b))
"""
0     11
1     44
2     99
3    176
dtype: int64
"""

combine 用起来还是很方便的,当然它同样是针对索引来操作的。此外combine和combine_first内部都会先对索引进行处理,如果两个 Series 对象的索引不一样,那么会先让它们索引变得一致。

import pandas as pd

s1 = pd.Series([1, 22, 3, 44], index=['a', 'b', 'c', 'd'])
s2 = pd.Series([11, 2, 33, 4], index=['c', 'd', 'e', 'f'])

# 先对两个索引取并集
index = s1.index.union(s2.index)
print(index) 
"""
Index(['a', 'b', 'c', 'd', 'e', 'f'], dtype='object')
"""

# 然后通过reindex,获取指定索引的元素
# 索引不存在就用 NaN 代替
s1 = s1.reindex(index)
s2 = s2.reindex(index)
print(s1)
"""
a     1.0
b    22.0
c     3.0
d    44.0
e     NaN
f     NaN
dtype: float64
"""
print(s2)
"""
a     NaN
b     NaN
c    11.0
d     2.0
e    33.0
f     4.0
dtype: float64
"""

combine 和 combine_first 都是先让 s1 和 s2 的索引变得一致之后,再进行操作。

import pandas as pd

s1 = pd.Series([1, 22, 3, 44],
               index=['a', 'b', 'c', 'd'])
s2 = pd.Series([11, 2, 33, 4],
               index=['c', 'd', 'e', 'f'])

print(s1.combine_first(s2))
"""
a     1.0
b    22.0
c     3.0
d    44.0
e    33.0
f     4.0
dtype: float64
"""

所以你会发现,s1 和 s2 里面都没有空值,返回的结果也没有空值,但是类型却从整型变成了浮点型。就是因为 s1 和 s2 在 reindex 的过程中出现了 NaN,所以类型变成了浮点型。

所以在使用 combine 和 combine_first 这两个方法的时候,一定要记住索引,否则可能会造成陷阱。事实上,包括 pandas 很多的其它操作也是,它们都是基于索引来的,并不是简单的依次从左到右或者从上到下。

update

update 比较野蛮,我们来看一下。

import pandas as pd

s1 = pd.Series([1, 2, 3, 4])
s2 = pd.Series([11, 22, 33, 44])

s1.update(s2)
print(s1)
"""
0    11
1    22
2    33
3    44
dtype: int64
"""

首先我们看到这个方法是在本地进行操作的,功能还是用 s2 的元素替换 s1 的元素,并且只要 s2 中的元素不为空,那么就进行替换。

import pandas as pd

s1 = pd.Series([1, 2, 3, 4])
s2 = pd.Series([11, 22, None, 44])

s1.update(s2)
print(s1)
"""
0    11
1    22
2     3
3    44
dtype: int64
"""

所以这个函数叫 update,意思就是更新。用 s2 中的元素换掉 s1 中的元素。但如果 s2 中的元素为空,那么可以认为新版本还没出来,那么还是使用老版本,所以 s1 中的 3 没有被换掉。

因此 update 和 combine_first 比较类似,但它们的区别在于:

  • combine_first:如果 s1 中的值为空,用 s2 的值替换,否则保留 s1 的值;
  • update:如果 s2 中的值不为空,那么替换 s1,否则保留 s1 的值;

另外在 combine_first 的时候,我们反复强调了索引的问题,如果 s1 和 s2 索引不一样,那么生成的结果的元素个数会增多。但是 update 不同,因为它是在本地进行操作的,也就是直接本地修改 s1,所以最终 s1 的元素个数是不会发生变化的。

import pandas as pd

s1 = pd.Series([1, 2, 3, 4], 
               index=['a', 'b', 'c', 'd'])
s2 = pd.Series([11, 22, 33, 44], 
               index=['c', 'd', 'e', 'f'])

s1.update(s2)
print(s1)
"""
a     1
b     2
c    11
d    22
dtype: int64
"""

s2 中不存在 index 为 a、b 的元素,那么可以认为新版本没有出现,因此不更新、保留原来的值。但 s2 中存在 index 为 c、d 的元素,所以有新版本,那么就更新。所以 s1 由 [1 2 3 4] 变成了 [1 2 11 22]。

至于 s2 中 index 为 e、f 的元素,它们和 s1 没有关系,因为 s1 中压根没有 index 为 e、f 的元素,s2 提供了新版本也是没用的。所以使用 update,是在 s1 本地操作的,操作前后 s1 的索引以及元素个数不会改变。

当然 update 也适用于对两个 DataFrame 进行操作,有兴趣可以自己去了解,但大部分时候我们都用在 Series 上面。

到此这篇关于详解Pandas如何高效对比处理DataFrame的两列数据的文章就介绍到这了,更多相关Pandas处理DataFrame数据内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • pandas进阶教程之Dataframe的apply方法

    目录 apply方法介绍 用例1 用例2 用例3 总结 apply方法介绍 方法形式为 apply(func, axis=0, raw=False, result_type=None, agrs=(), **kwargs),沿Dataframe的轴应用func函数. 传递给函数的对象是Series对象,当axis=0时,其索引是Dataframe的索引:当axis=1时,其索引是Dataframe的列. 默认情况下,result_type=None,最终返回的类型是从func函数的返回推断出来的

  • Pandas DataFrame操作数据增删查改

    目录 一.DataFrame数据准备 二.增删改查操作 1,增 2,查 3,改 4,删 一.DataFrame数据准备 增.删.改.查的方法有很多很多种,这里只展示出常用的几种. 参数inplace默认为False,只能在生成的新数据块中实现编辑效果.当inplace=True时执行内部编辑,不返回任何值,原数据发生改变. import numpy as np import pandas as pd #测试数据. df = pd.DataFrame(data = [['lisa','f',22]

  • pandas dataframe drop函数介绍

    使用drop函数删除dataframe的某列或某行数据: drop(labels, axis=0, level=None, inplace=False, errors='raise') -- axis为0时表示删除行,axis为1时表示删除列 常用参数如下:  import pandas as pd import numpy as np data = {'Country':['China','US','Japan','EU','UK/Australia', 'UK/Netherland'], '

  • 利用Pandas求两个dataframe差集的过程详解

    目录 1.交集 2.差集(df1-df2为例) 总结 1.交集 intersected=pd.merge(df1,df2,how='inner') 延伸(针对列求交集)intersected=pd.merge(df1,df2,on['name'],how='inner') 2.差集(df1-df2为例) diff=pd.concat([df1,df2,df2]).drop_duplicates(keep=False) 差集函数的详解: 1.Pandas 通过 concat() 函数能够轻松地将

  • pandas中字典和dataFrame的相互转换

    目录 一.字典转dataFrame 1.字典转dataFrame比较简单,直接给出示例: 二.dataFrame转字典 1.DataFrame.to_dict() 函数介绍 2.orient =‘dict’ 3. orient =‘list’ 4.orient =‘series’ 5.orient =‘split’ 6.orient =‘records’ 7.orient =‘index’ 8.指定列为key生成字典的实现步骤(按行) 9.指定列为key,value生成字典的实现 总结 一.字典

  • Python Pandas 修改表格数据类型 DataFrame 列的顺序案例

    目录 一.修改表格数据类型 DataFrame 列的顺序 1.1主要知识点 1.2创建 python 文件 1.3运行结果 二.Pandas 如何统计某个数据列的空值个数 2.1主要知识点 2.2创建 python 文件 2.3运行结果 三.Pandas如何移除包含空值的行 3.1主要知识点 3.2创建 python 文件 3.3运行结果 四.Pandas如何精确设置表格数据的单元格的值 4.1主要知识点 4.2创建 python 文件 4.3运行结果 一.修改表格数据类型 DataFrame

  • Python pandas按行、按列遍历DataFrame的几种方式

    目录 前言 一.按行遍历 1. 使用loc或iloc方法 2. 使用iterrows()方法 二.按列遍历 1. 使用列索引方式 2. 使用iteritems()方法 补充:遍历dataframe每一行的每一个元素 总结 前言 在对DataFrame数据进行处理时,存在需要对数据内容进行遍历的场景.因此记录一下按照行,列遍历的几种方式. 一.按行遍历 1. 使用loc或iloc方法 loc:表示location,填写内容为行的值或者列表,若填写内容为值,则返回对应行的内容(Series类型):若

  • Python Pandas实现DataFrame合并的图文教程

    目录 一.merge(合并)的语法: 二.以关键列来合并两个dataframe 三.理解merge时数量的对齐关系 1.one-to-one 一对一关系的merge 2.one-to-many 一对多关系的merge 3.many-to-many 多对多关系的merge 四.理解left join.right join.inner join.outer join的区别 1.inner join,默认 2.left join 3. right join 4. outer join 五.如果出现非K

  • Python  处理 Pandas DataFrame 中的行和列

    目录 处理列 处理行 前言: 数据框是一种二维数据结构,即数据以表格的方式在行和列中对齐.我们可以对行/列执行基本操作,例如选择.删除.添加和重命名.在本文中,我们使用的是nba.csv文件. 处理列 为了处理列,我们对列执行基本操作,例如选择.删除.添加和重命名. 列选择:为了在 Pandas DataFrame 中选择一列,我们可以通过列名调用它们来访问这些列. # Import pandas package import pandas as pd # 定义包含员工数据的字典 data =

  • 详解Pandas如何高效对比处理DataFrame的两列数据

    目录 楔子 combine_first combine update 楔子 我们在用 pandas 处理数据的时候,经常会遇到用其中一列数据替换另一列数据的场景.比如 A 列和 B 列,对 A 列中不为空的数据不作处理,对 A 列中为空的数据使用 B 列对应索引的数据进行替换.这一类的需求估计很多人都遇到,当然还有其它更复杂的. 解决这类需求的办法有很多,这里我们来推荐几个. combine_first 这个方法是专门用来针对空值处理的,我们来看一下用法. import pandas as pd

  • 详解pandas获取Dataframe元素值的几种方法

    可以通过遍历的方法: pandas按行按列遍历Dataframe的几种方式:https://www.jb51.net/article/172623.htm 选择列 使用类字典属性,返回的是Series类型 data['w'] 遍历Series for index in data['w'] .index: time_dis = data['w'] .get(index) pandas.DataFrame.at 根据行索引和列名,获取一个元素的值 >>> df = pd.DataFrame(

  • 详解pandas.DataFrame.plot() 画图函数

    首先看官网的DataFrame.plot( )函数 DataFrame.plot(x=None, y=None, kind='line', ax=None, subplots=False, sharex=None, sharey=False, layout=None,figsize=None, use_index=True, title=None, grid=None, legend=True, style=None, logx=False, logy=False, loglog=False,

  • 详解pandas中利用DataFrame对象的.loc[]、.iloc[]方法抽取数据

    pandas的DataFrame对象,本质上是二维矩阵,跟常规二维矩阵的差别在于前者额外指定了每一行和每一列的名称.这样内部数据抽取既可以用"行列名称(对应.loc[]方法)",也可以用"矩阵下标(对应.iloc[]方法)"两种方式进行. 下面具体说明: (以下程序均在Jupyter notebook中进行,部分语句的print()函数省略) 首先生成一个DataFrame对象: import pandas as pd score = [[34,67,87],[68

  • 详解pandas中iloc, loc和ix的区别和联系

    Pandas库十分强大,但是对于切片操作iloc, loc和ix,很多人对此十分迷惑,因此本篇博客利用例子来说明这3者之一的区别和联系,尤其是iloc和loc. 对于ix,由于其操作有些复杂,我在另外一篇博客专门详细介绍ix. 首先,介绍这三种方法的概述: loc gets rows (or columns) with particular labels from the index. loc从索引中获取具有特定标签的行(或列).这里的关键是:标签.标签的理解就是name名字. iloc get

  • 详解pandas绘制矩阵散点图(scatter_matrix)的方法

    使用散点图矩阵图,可以两两发现特征之间的联系 pd.plotting.scatter_matrix(frame, alpha=0.5, c,figsize=None, ax=None, diagonal='hist', marker='.', density_kwds=None,hist_kwds=None, range_padding=0.05, **kwds) 1.frame,pandas dataframe对象 2.alpha, 图像透明度,一般取(0,1] 3.figsize,以英寸为单

  • 详解Pandas 处理缺失值指令大全

    前言 运用pandas 库对所得到的数据进行数据清洗,复习一下相关的知识. 1 数据清洗 1.1 处理缺失数据 对于数值型数据,分为缺失值(NAN)和非缺失值,对于缺失值的检测,可以通过Python中pandas库的Series类对象的isnull方法进行检测. import pandas as pd import numpy as np string_data = pd.Series(['Benzema', 'Messi', np.nan, 'Ronaldo']) string_data.is

  • 详解pandas赋值失败问题解决

    一.pandas对整列赋值 这个比较正常,一般直接赋值就可以: x = pd.DataFrame({'A': ['1', '2', '3', None, None], 'B': ['4', '5', '6', '7', None]}) x['A'] = ['10', '11', '12', '13', '14'] 二.pandas对非整列赋值 1.用单个值赋值 x = pd.DataFrame({'A': ['1', '2', '3', None, None], 'B': ['4', '5',

  • 详解pandas映射与数据转换

    在 pandas 中提供了利用映射关系来实现某些操作的函数,具体如下: replace() 函数:替换元素: map() 函数:新建一列: rename() 函数:替换索引. 一.replace() 用映射替换元素 在数据处理时,经常会遇到需要将数据结构中原来的元素根据实际需求替换成新元素的情况.要想用新元素替换原来元素,就需要定义一组映射关系.在映射关系中,将旧元素作为键,新元素作为值. 例如,创建字典 fruits 用于指明水果标识和水果名称的映射关系. fruits={101:'orang

  • 详解pandas apply 并行处理的几种方法

    1. pandarallel (pip install ) 对于一个带有Pandas DataFrame df的简单用例和一个应用func的函数,只需用parallel_apply替换经典的apply. from pandarallel import pandarallel # Initialization pandarallel.initialize() # Standard pandas apply df.apply(func) # Parallel apply df.parallel_ap

随机推荐