Как я могу ссылаться на индекс моего фрейма данных Pandas?

у меня есть фрейм данных 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')

2 ответов


Я думаю, у вас есть небольшое недопонимание того, что такое индексы. Вы не просто "назначаете" столбцы индексами; то есть вы не просто "помечаете" определенные столбцы информацией, которая говорит "это индекс". Индекс-это отдельная структура данных, которая может содержать данные, которые не присутствуют в Столбцах. Если вы это сделаете set_index, вы движение эти столбцы в индекс, поэтому они больше не существуют как обычные столбцы. Вот почему вы больше не можете использовать их так, как упоминаете: они их больше нет.

одна вещь, которую вы можете сделать, это при использовании set_index, передать drop=False чтобы сказать ему сохранить столбцы как столбцы в дополнение к помещению их в индекс (эффективно копируя их в индекс, а не перемещая их), например, df.set_index('SomeColumn', drop=False). Однако вы должны знать, что индекс и столбец по-прежнему различны, поэтому, например, если вы измените значения столбцов, это не повлияет на то, что хранится в индексе.

в результате получается, что индексы на самом деле не столбцы фрейма данных, поэтому, если вы хотите использовать некоторые данные как индекс, так и столбец, вам нужно дублировать их в обоих местах. Существует некоторое обсуждение этого вопроса здесь.


информация доступна с помощью индекса get_level_values метод:

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. Одно из золотых правил проектирования баз данных, "никогда не повторяйте одни и те же данные в двух местах" так рано или позже данные станут непоследовательными и, таким образом, поврежденными. Поэтому я бы рекомендовал против сохранение данных как столбца, так и индекса, в первую очередь потому, что это может привести к повреждению данных, а также потому, что это может быть неэффективное использование памяти.