подмножество pandas с использованием нарезанного логического индекса

#python #pandas #indexing #dataframe #slice

#python #pandas #индексирование #фрейм данных #нарезать

Вопрос:

код для создания тестовых данных:

 import pandas as pd
import numpy as np

testdf = {'date': range(10),
      'event': ['A', 'A', np.nan, 'B', 'B', 'A', 'B', np.nan, 'A', 'B'],
      'id': [1] * 7   [2] * 3}
testdf = pd.DataFrame(testdf)

print(testdf)
  

дает

     date event  id
0     0     A   1
1     1     A   1
2     2   NaN   1
3     3     B   1
4     4     B   1
5     5     A   1
6     6     B   1
7     7   NaN   2
8     8     A   2
9     9     B   2
  

подмножество testdf

 df_sub = testdf.loc[testdf.event == 'A',:]
print(df_sub)
    date event  id
0     0     A   1
1     1     A   1
5     5     A   1
8     8     A   2
  

(Примечание: не переиндексировано)

создание условного логического индекса

 bool_sliced_idx1 = df_sub.date < 4
bool_sliced_idx2 = (df_sub.date > 4) amp; (df_sub.date < 6)
  

Я хочу вставить условные значения, используя этот новый индекс в исходном df, например

 dftest[ 'new_column'] = np.nan
dftest.loc[bool_sliced_idx1, 'new_column'] = 'new_conditional_value'
  

что, очевидно (сейчас), выдает ошибку:

 pandas.core.indexing.IndexingError: Unalignable boolean Series key provided
  

bool_sliced_idx1 выглядит так

 >>> print(bool_sliced_idx1)
0     True
1     True
5    False
8    False
Name: date, dtype: bool
  

Я пытался testdf.ix[(bool_sliced_idx1==True).index,:] , но это не работает, потому что

 >>> (bool_sliced_idx1==True).index
Int64Index([0, 1, 5, 8], dtype='int64')
  

Ответ №1:

IIUC, вы можете просто объединить все ваши условия сразу, вместо того, чтобы пытаться связать их. Например, df_sub.date < 4 действительно просто (testdf.event == 'A') amp; (testdf.date < 4) . Итак, вы могли бы сделать что-то вроде:

 # Create the conditions.
cond1 = (testdf.event == 'A') amp; (testdf.date < 4)
cond2 = (testdf.event == 'A') amp; (testdf.date.between(4, 6, inclusive=False))

# Make the assignments.
testdf.loc[cond1, 'new_col'] = 'foo'
testdf.loc[cond2, 'new_col'] = 'bar'
  

Что даст вам:

    date event  id new_col
0     0     A   1     foo
1     1     A   1     foo
2     2   NaN   1     NaN
3     3     B   1     NaN
4     4     B   1     NaN
5     5     A   1     bar
6     6     B   1     NaN
7     7   NaN   2     NaN
8     8     A   2     NaN
9     9     B   2     NaN
  

Комментарии:

1. Да, это верно, потому что, если вы не соедините их в цепочку и получите условие из df_sub , ваш логический индекс не будет иметь одинаковой длины, и поэтому возникнет ошибка!

Ответ №2:

Это сработало

 idx = np.where(bool_sliced_idx1==True)[0]
## or 
# np.ravel(np.where(bool_sliced_idx1==True))

idx_original = df_sub.index[idx]
testdf.iloc[idx_original,:]