Pandas 索引对齐、缺失值

这篇博客探讨了Pandas中Series和DataFrame对象在进行二元运算时的索引对齐规则,以及由此产生的缺失值处理。当两个Series运算时,结果的index是两者的并集,而DataFrame则会根据列名和行数进行对齐,形状不匹配的部分填充NaN。Pandas提供了多种处理NaN的方法,如isnull()、notnull()、fillna()和dropna(),可以进行发现、剔除或填充缺失值。此外,介绍了如何使用通用函数进行特定轴的运算,避免直接使用算术运算符导致的列运算问题。

开篇

当在进行Series、DataFrame这两个对象的二元运算时,有稍不同于Numpy的处理方式。

本篇将以组合不同来源的数据为起点,探究其中发生的索引对齐,过程中产生的缺失值的特性和处理手段,以及更进一步的数据集合并方法。

引子——Pandas的NumPy-based特性

因为Pandas是建立在NumPy的基础之上的,所以NumPy的通用函数仍适用于Series对象和DataFrame对象。你可以在NumPy的通用函数里传入一个Series对象,会返回一个保留索引的Pandas对象。*下面代码中的randomstate是随机数种子的意思

import numpy as np
import pandas as pd

ser=pd.Series(np.random.RandomState(42).randint(0,10,4))#ndarray可以用来创建Series
print(np.exp(ser))#Series可以传入NumPy的方法

一、索引对齐与集合运算规则

1.1 两个Series,index的并集

简言之,对两个不同的Series进行二元运算得到的新的Series对象的index将是原来两个的Series的并集。

import pandas as pd

score_math = pd.Series({'小明':58,'小丁':79,'小红':84,'小华':98})
score_English = pd.Series({'小陈':72,'小卡':100,'小红':84,'小明':89})

print(score_math+score_English)
#只要不是共有的index对应的数值一定是NaN

 很多NaN,很难受,这也和NaN本身的特性有关系,稍后会提到。

1.2  两个DataFrame,类似的并集

在介绍DataFrame的对齐之前,需要先入为主的是——DataFrame很贴心,我哭死。

1.2.1 一个之后会用到的构造函数来减少我的书写量

import pandas as pd
def make_df(cols,ind):
    data=pd.DataFrame({c:[str(c)+str(i) for i in ind] for c in cols})
    return data


#易读版
import pandas as pd
def make_df_easy(cols,ind):
    datadict={}
    datalist=[]
    for c in cols:
        for i in ind: 
            datalist.append(str(c)+str(i))
        datadict[c]=datalist
        datalist=[]
    data=pd.DataFrame(datadict)
    return data


以下是测试语句,可以拿去试试
df1=make_df_easy('ABC',[1,2,3])
print('df1是\n',df1)


df2=make_df('DEF',[1,2,3])
print('df2是\n',df2)

1.2.2 如果这两个DataFrame的列名(columns)完全相同(顺序无所谓),对应index个数也相等(说到底就是形状一样)

df1=make_df('ABC',[1,2,3])
df2=make_df('CAB',[6,7,8])

print(df1+df2)

1.2.3 只要形状不一样,不一样的地方就是NaN

df1=make_df('ABC',[1,2,3])

df2=make_df('CA',[6,7])

df3=make_df('CAE',[5,6,7])

print(df1+df2)
print(df1+df3)

在第一个print中,列会取并集得到A、B、C,三列,但是B列是不会有值的,且由于df2只有两行 ,就算df1有三行,第三行也将全是NaN。

有一点木桶效应的意思在里面,虽然最后得到的形状是向外兼容最大的并集,但实际有效的数据是交出来的,在第一个print里体现为,会有ABC三列,每列三行,但只有AC两列中的两行是有效的,在第二个print中体现为,会有ABCE四列,每列三行,但只有AC两列的三行是有效的

1.3 一个Series和一个DataFrame呢? 

如果我们回想NumPy中的广播,比如拿一个二维数组(shape=(3,4)),减一个长度为4的一维数组,结果会体现成每一行分别对应减去了这个一维数组里的值(如第一行第一个减一维数组中第一个,第二个减第二个……第二行第一个减一维中第一个……)

一个DataFrame和一个Series做运算,也是按行来的。需要注意的是,Series的index在进行索引对齐的时候(因为默认是一行一行的),index会与DataFrame的column对齐  

import pandas as pd
import numpy as np
df=pd.DataFrame(np.arange(12).reshape((3,4)),columns=list('QRST'))
ser=pd.Series([13,5,18,65],index=list('QRST'))
print(df)
print(df-ser)

你是不能直接的用算术运算符来做出列运算的效果

1.4 但你可以用正儿八经的通用函数

Python运算符与Pandas方法的映射关系
Python运算符Pandas方法
+                加法add ( )

-                减法

sub( )   subtract()
*                乘法mul() multiply()
/                除法truediv() div() divide()
//                地板除floordiv()
%                取余mod()
**                乘方pow()

只需要指定轴就可以了👇,注意Series的长度就行

import pandas as pd
import numpy as np
df=pd.DataFrame(np.arange(12).reshape((3,4)),columns=list('QRST'))
ser=pd.Series([13,5,18])
print(df)
print(df.subtract(ser,axis=0))

你也可以利用DataFrame自身的行与列

比如
如果是行还是直接减就可以了
df-df[0]

列的话↓
df.subtract(df['R'],axis=0)#减去R列的值

通用函数不止是可以针对轴,也可以对缺失值作出处理,也可以决定索引对齐的层级。

第一部分只是让你对并集是个啥有个大概的概念,以及得到一些缺失值

二、我们关注缺失值

Pandas选择的是标签方法来表示缺失值,包括两种原有的Pythono缺失值:浮点数据类型的NaN值(也是数值类型的缺失值)和None对象(Python对象类型的缺失值)。由于本文的入门性,就不在这里阐释None

当一个数组包含None的时候,如果你对这个数组进行累计操作,比如求和,求最值这样的聚合函数,通常会出现TypeError——Python是没定义None和一些数据的计算的(比如整数)

2.1 NaN,数值病毒(更像是传染孢子)

无论你的数据和NaN进行何种操作,结果都将是NaN    : ),不会抛出异常,但结果都是NaN

import numpy as np
print(1+np.nan)
print(0*np.nan)
print(np.array([1,np.nan,2,48]).sum())
print(np.array([1,np.nan,2,48]).max())

2.2 如何处理缺失值——发现,剔除,替换

2.2.(0.5) 可以忽略缺失值的方法(numpy里的)

np.nansum() , np.nanmin(), np.nanmax()_可以套到2.1中的代码块里来看

2.2.1 快把它弄出来,快把它弄出来!

两个有效的方法发现缺失值—— isnull( ) 和 notnull( ),返回一个布尔数组,你可以从True和False里再结合函数名判断它是不是缺失值。

然后根据DataFrame的NumPy-based的特点,我们其实可以通过传入这个布尔数组来对空值或者非空值进行索引,在前面提到的链接中你也能看到这一部分的内容。

这样的索引一般在Series里才有点作用。(Series[Series.notnull ( ) ])

2.2.2 滚出加基森(可以填补什么,可以怎么填补)

剔除有两种形式,删掉和补上。dropna() 和 fillna()

对于一维的Series直接用就行了,dropna()会直接抹除Series中的缺失值,而在fillna()中,你可以设置:

传入的值和填补的方式

你可以传入什么?单一的标量,缺失值位置前后的值,一些特定的量(比如平均数),一个字典,字典的键决定你要填补的列,然后字典键对应的值则用来填充那一列所有缺失值

注意你要传入的字典是单纯的字典,那个字典的键只能对应一个值

不要妄想让一个列表字典去个性化的填充缺失值(你可能想着如果这一列有两个缺失值,那我一个字典,键对应一个两个元素的列表依次填进去)但这行不通。

下面的代码介绍的是method参数

import pandas as pd
data=pd.Series([1,np.nan,2,None,3,5],index=list('abcdef'))

print(data.fillna(0))

print(data.fillna(method='ffill'))

method有几个可取值 backfill bfill>>>用后一个非缺失值去填充该缺失值
ffill/pad>>>用前一个非缺失值去填充该缺失值

在用这种“位置方法”,如果一个缺失值的相应位置没有可以拿来填的数字,那么它继续成为NaN

·  你可以指定最多几个被fill >> limit参数—— 一个整数,决定了你最多填补几个

·  你可以指定对原数组删补还是返回一个新数组 >> inplace参数,默认false,函数会返回一个新的被删补的pandas对象,设置为True则对原数组进行删补,返回值是空(None),意思是你试图把一个inplace=True的这个方法的返回值传入并打印新变量是无意义的。 

2.2.3 DataFrame 更多的要求

对于DataFrame来说,由于是二维,删除和填充的时候需要设置坐标轴。当然想要达到某种填充效果还是可以用method参数。由于是二维,删除单个的缺失值是没有意义的,你删除了他还相当于是缺失,因此只能剔除NaN所在的一整行或者一整列

你当然会注意到这样也会把非缺失值给去掉,因此我们可以通过调整dropna()的参数来调整

how参数:如果是 'all',则只有这一行/列全为缺失它才会被删除,如果是"any",则只要有缺失值它就会被删除

tresh参数:设置非缺失值的最小数量MIN。如果在某列/行中,非缺失值的个数比MIN还小了,那他就肯定会被删掉了。

下一次将讨论数据集合并与分组

<think>首先,用户的问题是基于提供的参考资料:"我想查找使用Pandas根据索引判断值的正确性的方法 请问Pandas如何根据索引判断值的正确性"。实际上,用户是在问如何用Pandas根据索引来验证数据的正确性。 系统级指令回顾: - 所有行内数学表达式必须使用 $...$ 格式。 - 独立公式用 $$...$$ 格式,单独成段。 - LaTeX语法正确。 - 使用中文回答。 - 生成相关问题。 - 回答中引用的段落末尾自然地添加引用标识,例如 [^1]。 - 回答结构清晰,帮助用户逐步解决问题,尽量保证回答真实可靠。 参考资料: - [^1]:索引是一个非常重要的概念,为数据的选择、切片、对齐等操作提供了基础。 - [^2]:索引在数据合并、分组聚合等操作中发挥决定性作用。 - [^3]:读取csv数据时使用index_col指定索引。 用户上一次的问题或对话历史:从上下文看,这是用户的问题,没有之前的对话历史。系统提示说“请尽可能多的参考用户上一次的问题和你的回答”,但在这里,这是第一次交互,所以我应该基于当前引用和问题。 用户的问题:"使用Pandas根据索引判断值的正确性"。我需要解释如何用索引来验证数据的正确性。索引Pandas中主要用于标识数据,但直接“判断值的正确性”可能涉及数据验证,比如检查索引是否匹配或基于索引比较值。 关键点: - 索引用于标识数据,使得选择、切片和操作更高效。 - 在数据合并时,索引可以帮助对齐数据。 - 用户可能想检查数据是否正确对齐索引是否唯一等。 可能的含义: - 用户可能想验证数据的完整性,比如通过索引确保数据一致。 - 例如,比较两个DataFrame的索引来匹配值。 - 或者使用索引来过滤错误的行。 回答结构: - 结构化回答:逐步解释。 - 使用中文。 - 生成相关问题。 步骤: 1. **解释索引的作用**:基于引用,索引是基础,用于标识和操作数据。 2. **如何根据索引判断值的正确性**: - 检查索引是否唯一:使用 `.index.is_unique` 来判断是否有重复索引。 - 使用索引进行数据对齐:在操作如加法或合并时,值会根据索引对齐。 - 比较两个数据集的索引:使用 `.index.equals()` 来判断索引是否相同。 - 索引基于值过滤:比如使用布尔索引来筛选特定条件的行。 - 处理缺失值:基于索引检查是否有缺失值。 - 例子:假设有两个DataFrame,df1 和 df2,使用 `df1.join(df2)` 会根据索引对齐,如果索引不一致,值可能不匹配。 具体方法: - **验证索引一致性**:在数据合并前,检查 `.index` 是否匹配。 - **使用 `.loc` 进行精确选择**:确保通过索引访问的值正确。 - **索引用于条件检查**:例如,df.index 可以用于布尔索引来过滤数据。 - **处理重复索引**:使用 `.drop_duplicates()` 或 `.loc` 避免错误。 由于引用提到的: - 引用[1]:索引用于选择、切片、对齐。 - 引用[2]:索引在合并和分组中关键。 - 引用[3]:指定索引。 在回答中引用这些,自然地添加引用标识。 最后,生成相关问题。 完整回答结构: 1. 引言:解释索引Pandas中的作用。 2. 方法:逐步描述如何根据索引判断值的正确性。 3. 例子:提供简单的代码示例(使用中文注释)。 4. 总结。 5. 生成相关问题。 代码部分:既然示例中有Python代码,我可以提供Pandas代码片段。 确保LaTeX:如果有数学表达式,使用 $...$。但在这个上下文中,可能没有数学公式;主要是数据操作。如果有,比如讨论索引值,使用 $index$。 现在,草拟回答: </think>### 使用 Pandas 根据索引判断值的正确性 在 Pandas 中,索引(Index)是数据结构的核心组件,它为数据提供了高效的标识和访问机制。索引在数据选择、对齐、合并等操作中起着决定性作用,通过索引可以验证数据的完整性、一致性和正确性[^1][^2]。例如,索引能帮助检测缺失值、重复值或不匹配数据,确保数据集的可靠性。以下我将逐步解释如何根据索引判断值的正确性,并提供具体方法。 #### 1. **理解索引的作用** - 索引Pandas 中用于唯一标识数据行或列,便于高效定位和操作数据。例如,在读取数据时指定索引(如 `index_col='ID'`)可以使后续操作更精确[^3]。 - 索引的正确性直接影响数据分析的准确性:如果索引不唯一或不一致,可能导致数据选择错误、合并失败或值误判[^2]。 #### 2. **判断值的正确性的方法** 基于索引验证数据正确性的核心思路是利用索引的标识功能,通过比较、对齐或过滤来检测异常。以下是几种常见方法: - **检查索引唯一性**:索引不唯一可能导致数据重叠或冲突。使用 `.index.is_unique` 属性可以快速判断索引是否唯一。如果返回 `False`,说明存在重复索引,值可能不可靠。 ```python import pandas as pd # 示例:创建 DataFrame 并检查索引唯一性 data = {'Value': [10, 20, 30]} df = pd.DataFrame(data, index=['A', 'B', 'B']) # 索引 'B' 重复 print(f"索引是否唯一: {df.index.is_unique}") # 输出: False,表示值可能存在冲突 ``` - **使用索引对齐比较值**:在合并或计算时,索引会自动对齐数据。如果索引不匹配,值可能不正确。通过 `.equals()` 方法比较两个数据集的索引是否相同,并用 `.loc` 精确选择值进行验证。 ```python # 示例:比较两个 DataFrame 的索引和值 df1 = pd.DataFrame({'Value': [10, 20]}, index=['A', 'B']) df2 = pd.DataFrame({'Value': [20, 30]}, index=['B', 'C']) # 步骤 1: 检查索引是否一致 if df1.index.equals(df2.index): print("索引一致,值可直接比较") else: print("索引不一致,值可能不对齐") # 输出此结果 # 步骤 2: 基于索引精确选择值进行验证 (例如,验证索引 'B' 的值是否正确) value_at_index_B = df1.loc['B', 'Value'] # 取出 df1 中索引 'B' 的值 if value_at_index_B == df2.loc['B', 'Value']: # 比较 df2 中相同索引的值 print(f"索引 'B' 的值正确: {value_at_index_B}") else: print(f"索引 'B' 的值错误: {value_at_index_B} vs {df2.loc['B', 'Value']}") ``` - **过滤基于索引的异常值**:索引可用于布尔索引筛选,以检测或删除不正确的值。例如,结合条件表达式过滤索引范围外的数据。 ```python # 示例:过滤索引值超出预期的数据 df = pd.DataFrame({'Value': [100, 200, 300]}, index=[1, 2, 3]) expected_indices = [1, 2] # 假设索引应为 1 或 2 # 创建布尔掩码,判断索引是否在预期范围内 valid_mask = df.index.isin(expected_indices) invalid_data = df[~valid_mask] # 获取索引不在预期范围内的数据 if not invalid_data.empty: print(f"发现异常值: \n{invalid_data}") # 输出索引 3 的值,可能错误 # 可选: 删除异常值 df_valid = df[valid_mask] ``` - **处理索引缺失或无效值**:索引缺失会导致值无法对齐。使用 `.reindex()` 填充缺失索引或用 `.dropna()` 清理无效值。 ```python # 示例:检查索引缺失导致的无效值 df = pd.DataFrame({'Value': [40, 50]}, index=['X', 'Y']) reference_index = ['X', 'Y', 'Z'] # 参考索引(应包含所有有效索引) # 重新索引并填充缺失值,NaN 表示索引缺失 df_reindexed = df.reindex(reference_index) print(df_reindexed) # 输出: # Value # X 40.0 # Y 50.0 # Z NaN # 索引 'Z' 缺失,值无效 # 判断正确性:检查是否有 NaN 值 if df_reindexed['Value'].isna().any(): print("存在索引缺失的错误值") # 输出此结果 ``` #### 3. **常见场景和最佳实践** - **数据合并时对齐索引**:在 `merge()` 或 `join()` 操作中,索引确保值正确匹配。如果合并失败(如出现 NaN),说明索引不一致导致值错误[^2]。 - **分组聚合验证**:索引在 `groupby()` 中定义分组规则,错误索引可能使聚合值不准确。始终先检查索引唯一性。 - **性能提示**:索引操作高效,适用于大数据集。优先使用 `.loc` 而非 `.iloc` 以确保基于索引的精确访问[^1]。 - **错误排查**:如果值异常,先检查索引是否设置正确(例如 `df.index` 输出),处理重复索引可用 `df.index.duplicated().sum()`。 总之,通过索引判断值的正确性依赖于索引的标识和对齐功能。核心步骤是先验证索引特性(如唯一性和一致性),再基于索引选择或比较值。这样可以有效捕捉数据错误,提升分析可靠性[^1][^2][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值