2015-02-17 2 views
1

Я пытаюсь узнать, как подмножество работает в pandas DataFrame. Я сделал случайный фрейм данных, как показано ниже.Подмножество DataFrame с использованием ix в Python

import pandas as pd 
import numpy as np 

np.random.seed(1234) 
X = pd.DataFrame({'var1' : np.random.randint(1,6,5), 'var2' : np.random.randint(6,11,5), 
        'var3': np.random.randint(11,16,5)}) 
X = X.reindex(np.random.permutation(X.index)) 
X.iloc[[0,2], 1] = None 

X возвращается,

var1 var2 var3 
0  3 NaN 11 
4  3  9 13 
3  2 NaN 14 
2  5  9 12 
1  2  7 13 

панды метод .loc строго этикеток на основе и .iloc для целочисленных позиций. .ix можно использовать для комбинирования позиционных индексов и меток.

Однако в приведенном выше примере индексы строк являются целыми числами, а .ix понимает их как индексы строк, а не позиции. Предположим, что я хочу получить первые две строки «var2». В R, X[1:2, 'var2'] даст ответ. В Python X.ix[[0,1], 'var2'] возвращает NaN 7, а не NaN 9.

Вопрос: «Есть ли простой способ дать .ix знать, что индексы основаны на позиции?»

Я нашел некоторые решения для этого, но в некоторых случаях они не простые и интуитивные.

Например, используя _slice(), как показано ниже, я мог бы получить результат, который хотел.

>>> X._slice(slice(0, 2), 0)._slice(slice(1,2),1) 
    var2 
0 NaN 
4  9 

Когда индексы строк не являются целыми числами, проблем нет.

>>> X.index = list('ABCED') 
>>> X.ix[[0,1], 'var2'] 
A NaN 
B  9 
Name: var2, dtype: float64 
+0

Но у вас есть метод индексирования с использованием целочисленного местоположения, поэтому почему бы просто не использовать 'iloc', чтобы избежать неоднозначной индексации? – EdChum

+0

@EdChum Да, 'X.iloc [[0,1], 1]' возвращает подмножество, но есть случай, когда вы знаете только имя атрибута 'var2'. – NeoJi

+0

@EdChum Возможно, вы правы. Я не мог придумать ни одного случая, что я знаю только имена атрибутов. Думаю, я зашел слишком далеко. – NeoJi

ответ

1

Вы можете использовать X['var2'].iloc[[0,1]]:

In [280]: X['var2'].iloc[[0,1]] 
Out[280]: 
0 NaN 
4  9 
Name: var2, dtype: float64 

С X['var2'] является вид из X, X['var2'].iloc[[0,1]] безопасен как для доступа и назначений. Но будьте осторожны, если вы используете этот шаблон «цепной индексации» (например, используемый здесь образец по умолчанию-column-then-index-by-iloc) для присвоений, поскольку он не обобщает на случай присвоений с несколькими колонны.

Например, X[['var2', 'var3']].iloc[[0,1]] = ... генерирует копию из в суб-DataFrame Х так отнесение к этой суб-DataFrame не изменяет X. См. Документы на "Why assignments using chained indexing fails" для более подробного объяснения.

Чтобы быть конкретным и показать, почему эта точка зрения-против-копии различие важно: Если у вас есть это предупреждение включено:

pd.options.mode.chained_assignment = 'warn' 

этот правопреемником поднимает SettingWithCopyWarning предупреждение:

In [252]: X[['var2', 'var3']].iloc[[0,1]] = 100 
SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a 
DataFrame 
See the the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy 
    self._setitem_with_indexer(indexer, value) 

, и назначение не может изменить X. Ик!

In [281]: X 
Out[281]: 
    var1 var2 var3 
0  3 NaN 11 
4  3  9 13 
3  2 NaN 14 
2  5  9 12 
1  2  7 13 

Чтобы обойти эту проблему, если вы хотите присваивание повлиять X, вы должны присвоить одной индексатор (например, X.iloc = ... или X.loc = ... или X.ix = ...) - то есть, без индексирование цепей.

В этом случае, вы можете использовать

In [265]: X.iloc[[0,1], X.columns.get_indexer_for(['var2', 'var3'])] = 100 

In [266]: X 
Out[266]: 
    var1 var2 var3 
0  3 100 100 
4  3 100 100 
3  2 NaN 14 
2  5  9 12 
1  2  7 13 

, но мне интересно, если есть лучший способ, так как это не очень красиво.