处理数据的时候, 我们经常需要从dataframe里根据行和列的条件提取特定格子的值, 比如下面的一段代码:
import pandas as pd
list_1 = [
{'a':1,'b':1,'value':10},
{'a':1,'b':2,'value':20},
{'a':2,'b':1,'value':30},
{'a':2,'b':2,'value':40},
]
df = pd.DataFrame(list_1).set_index(['a','b'])
df.loc[(1,2),'value']
上述代码将a和b共同作为index (多重index在很多时候有不错的应用), 返回结果是20, 类型是numpy.int64
. 如果将代码做一下修改, 给数据框增加一行:
import pandas as pd
list_2 = [
{'a':1,'b':1,'value':10},
{'a':1,'b':2,'value':20},
{'a':2,'b':1,'value':30},
{'a':2,'b':2,'value':40},
# 下面是新增的一行
{'a':2,'b':2,'value':45},
]
df = pd.DataFrame(list_2).set_index(['a','b'])
df.loc[(1,2),'value']
a为2,b为2的情况多了一个value为45的记录, 现在再用df.loc[(1,2),'value']
虽然还是只有{'a':1,'b':2,'value':20}
匹配, 但是仍旧是以pandas.core.series.Series
的形式返回, 这个可以自己去用type命令印证一下.
为什么会这样呢?
我们先看另外一个dataframe
import pandas as pd
list_3 = [
{'a':1,'value':10},
{'a':2,'value':20},
{'a':2,'value':30},
]
df = pd.DataFrame(list_3).set_index('a')
print(df.loc[1,'value'],type(df.loc[1,'value']))
print(df.loc[2,'value'],type(df.loc[2,'value']))
上面代码两个print输出的结果分别是:
10 <class 'numpy.int64'>
a
2 20
2 30
Name: value, dtype: int64 <class 'pandas.core.series.Series'>
从上面三个例子可以看到:
- 在单一index的情况下, 如果loc匹配的结果是唯一的, 会直接返回匹配的值, 如果不是唯一的, 会返回所有结果组成的Series.
- 在多重index的情况下, 如果index中没有重复值(第一个例子), 则loc直接返回匹配的值
- 在多重index的情况下, 如果index中有重复值(第二个例子), 则loc无论匹配的是不是唯一值, 都会返回所有结果组成的Series
这就会给程序带来很大的不确定性, 所以在使用loc以前, 真的很应该了解一下你的index是不是有重复值的. 好吧, pandas在使用set_index的时候是允许index中出现重复值的.
这个检验并不难做, 以第二个例子的代码做点更改:
import pandas as pd
list_2 = [
{'a':1,'b':1,'value':10},
{'a':1,'b':2,'value':20},
{'a':2,'b':1,'value':30},
{'a':2,'b':2,'value':40},
{'a':2,'b':2,'value':45},
]
df = pd.DataFrame(list_2).set_index(['a','b'])
index_is_duplicated = df.index.duplicated()
print(index_is_duplicated)
输出的结果是[False False False False True]
, 最后一项的index和之前重复了, 所以结果是True
, 如果只是单纯想判断一下有没有重复值, 求一下和然后判断是否大于0就好了.
如果发现index有重复值, 这个时候就要具体情况具体分析了, 但是首先还是应该明确到底有没有重复, 对吧