Pandas DataFrame: выделение нескольких элементов в нескольких столбцах - PullRequest
0 голосов
/ 22 ноября 2018

У меня есть этот DataFrame Python Pandas DF:

DICT = {  'letter': ['A','B','C','A','B','C','A','B','C'],
          'number': [1,1,1,2,2,2,3,3,3],
          'word'  : ['one','two','three','three','two','one','two','one','three']}

DF = pd.DataFrame(DICT)

, который выглядит так:

  letter  number   word
0      A       1    one
1      B       1    two
2      C       1  three
3      A       2  three
4      B       2    two
5      C       2    one
6      A       3    two
7      B       3    one
8      C       3  three

И я хочу извлечь строки

  letter  number   word
       A       1    one
       B       2    two
       C       3  three

Сначала я устал:

DF[(DF['letter'].isin(("A","B","C"))) & 
    DF['number'].isin((1,2,3))        &
    DF['word'].isin(('one','two','three'))]

Конечно, это не сработало, и все было выбрано

Затем я проверил:

Bool = DF[['letter','number','word']].isin(("A",1,"one"))
DF[np.all(Bool,axis=1)]

Хорошо, это работает!но только для одной строки ... Если мы сделаем следующий шаг и дадим итерируемое значение .isin():

Bool = DF[['letter','number','word']].isin((("A",1,"one"),
                                            ("B",2,"two"),
                                            ("C",3,"three")))

Тогда произойдет сбой, логический массив заполнен False ...

Что я делаю не так?Есть ли более элегантный способ сделать этот выбор, основанный на нескольких столбцах?

(Во всяком случае, я хочу избежать цикла for, потому что реальные фреймы данных, которые я использую, действительно большие, поэтому яищу самый быстрый и оптимальный способ выполнения работы)

1 Ответ

0 голосов
/ 22 ноября 2018

Идея заключается в создании нового DataFrame со всеми тройными значениями, а затем merge с оригинальным DataFrame:

L = [("A",1,"one"),
     ("B",2,"two"),
     ("C",3,"three")]

df1 = pd.DataFrame(L, columns=['letter','number','word'])
print (df1)
  letter  number   word
0      A       1    one
1      B       2    two
2      C       3  three

df = DF.merge(df1)
print (df)
  letter  number   word
0      A       1    one
1      B       2    two
2      C       3  three

Другая идея - создать список кортежей, преобразовать вSeries и затем сравните на isin:

s = pd.Series(list(map(tuple, DF[['letter','number','word']].values.tolist())),index=DF.index)
df1 = DF[s.isin(L)]
print (df1)
  letter  number   word
0      A       1    one
4      B       2    two
8      C       3  three
...