Pandas中引用DataFrame元素的函数里'is'与'=='的异常行为
问题解答
一、获取指定位置元素的高效内置方法
不用自己编写函数,pandas内置的iloc(按位置索引)和loc(按标签索引)就是最安全高效的方式:
- 按行/列的位置索引:
df.iloc[row_position, col_position] - 按行/列的标签索引:
df.loc[row_label, col_label]
你自己写的datframe[col][row]属于链式索引,存在返回副本的风险,官方更推荐使用iloc/loc的单步索引方式。
二、is判断出现差异的底层原因
先还原你的测试案例:
df = pd.DataFrame({'A': ['one', 'two', 'three'] , 'B': ['foo', 'bar', 'foo'], 'C':[1,2,3], 'D':[4,5,6]}, index = [0,1,2]) def testr(datframe,row,col): return datframe[col][row] # 字符串元素判断 print(df.loc[0,'B'] is testr(df,0,'B')) # 输出True # 数值元素判断 print(df.loc[0,'C'] is testr(df,0,'C')) # 输出False
1. 字符串元素is判断为True的原因
Python对短字符串、常用字符串会做**字符串驻留(string interning)**优化——相同内容的字符串会被存在内存的同一个位置,复用同一个对象引用。
而pandas的字符串列(object类型)存储的就是Python字符串对象的引用,所以不管是通过loc还是链式索引取出的字符串,都是指向同一个驻留的字符串对象,is判断自然返回True。
2. 数值元素is判断为False的原因
pandas的数值列(比如int、float)是基于numpy数组存储的,numpy数组会把数值以原始二进制的形式存在连续内存块里,而非存储Python对象的引用。
当你取出单个数值时,pandas会把numpy里的原始数值重新包装成一个新的Python int/float对象返回。哪怕是同一个位置的数值,每次取出都会生成一个新的Python对象,两个对象的内存地址不同,所以is判断返回False。
3. ==判断正常的原因
==判断的是值的相等性,只要两个对象的内容一致就返回True;而is判断的是对象引用的同一性,只有两个变量指向内存中同一个对象时才会返回True。
内容的提问来源于stack exchange,提问作者gcfitzgerald
相关产品推荐
相关产品推荐

