我有一个Pandas数据框,我将一些列指定为索引:
planets_dataframe.set_index(['host','name'], inplace=True)
并希望能够在各种情况下引用这些指数。使用索引名称可以在查询中正常工作
planets_dataframe.query('host == "PSR 1257 12"')
但如果尝试使用它来获取索引值的列表,则会导致错误,因为它可能是列
planets_dataframe.name
#AttributeError: 'DataFrame' object has no attribute 'name'
或使用它来列出结果,因为它是“常规”列
planets_dataframe.query('30 > mass > 20 and discoveryyear > 2009')['name']
#KeyError: u'no item named name'
如何引用我用作索引的数据框的“列”?
在set_index
之前:
planets_dataframe.columns
# Index([u'name', u'lastupdate', u'temperature', u'semimajoraxis', u'discoveryyear', u'calculated', u'period', u'age', u'mass', u'host', u'verification', u'transittime', u'eccentricity', u'radius', u'discoverymethod', u'inclination'], dtype='object')
set_index
之后:
planets_dataframe.columns
#Index([u'lastupdate', u'temperature', u'semimajoraxis', u'discoveryyear', u'calculated', u'period', u'age', u'mass', u'verification', u'transittime', u'eccentricity', u'radius', u'discoverymethod', u'inclination'], dtype='object')
答案 0 :(得分:14)
我认为你对索引有一点误解。您不只是将“指定”列作为索引;也就是说,您不仅仅使用“这是一个索引”的信息“标记”某些列。索引是一个单独的数据结构,可以保存列中甚至不存在的数据。如果您执行set_index
,则将这些列移动到索引中,因此它们不再作为常规列存在。这就是为什么你不能再以你提到的方式使用它们了:它们不再存在了。
您可以做的一件事是,在使用set_index
时,传递drop=False
告诉它将列保留为列除了将它们放入索引之外(有效地将它们复制到索引而不是移动他们),例如df.set_index('SomeColumn', drop=False)
。但是,您应该知道索引和列仍然是不同的,因此,例如,如果您修改列值,这将不会影响索引中存储的内容。
结果是索引不是DataFrame的真正列,因此如果您希望能够将某些数据用作索引和列,则需要在两个位置复制它。对此问题进行了一些讨论here。
答案 1 :(得分:3)
可以使用索引get_level_values
method:
import numpy as np
import pandas as pd
np.random.seed(1)
df = pd.DataFrame(np.random.randint(4, size=(10,4)), columns=list('ABCD'))
idf = df.set_index(list('AB'))
idf.index.get_level_values('A')
大致相当于df['A']
。但请注意类型和dtype的变化:
print(df['A'])
# 0 1
# 1 3
# 2 3
# 3 0
# 4 2
# 5 2
# 6 3
# 7 1
# 8 3
# 9 3
# Name: A, dtype: int32
def level(df, lvl):
return df.index.get_level_values(lvl)
print(level(idf, 'A'))
# Int64Index([1, 3, 3, 0, 2, 2, 3, 1, 3, 3], dtype='int64')
再次在这里,您可以使用['A']
获取等效信息,而不是选择.index.get_level_values('A')
列:
print(df.query('3>C>0 and D>0')['A'])
# 8 3
# Name: A, dtype: int32
print(level(idf.query('3>C>0 and D>0'), 'A'))
# Int64Index([3], dtype='int64')
PS。数据库设计的一个重要规则是“永远不要在两个地方重复相同的数据”,因为数据迟早会变得不一致并因此被破坏。所以我建议反对将数据保持为列和索引,主要是因为它可能导致数据损坏,但也因为它可能是对内存的低效使用。