Выбор строки по нескольким критериям столбца в кадре данных мути-индекса (более эффективное решение?) - PullRequest
2 голосов
/ 20 июня 2019

У меня есть фрейм данных, который состоит из множества столбцов 'ratio' (67 столбец: ratio_1 - ratio_67). На основе этих столбцов я хочу создать новый столбец в моем фрейме данных с записью «pass» или «fail»

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

import random
col3=[0,0,0,0,2,4,6,0,0,0,100,200,300,400]
col4=[0,0,0,0,4,6,8,0,0,0,200,900,400, 500]
listt = [np.nan, np.nan , 1, 1, 1, 5, 5, 1, 1,np.nan ,np.nan ]

col5 = [listt[random.randrange(len(listt))]
              for item in range(14)]
col6 = [listt[random.randrange(len(listt))]
              for item in range(14)]
col7 = [listt[random.randrange(len(listt))]
              for item in range(14)]
col8 = [listt[random.randrange(len(listt))]
              for item in range(14)]


df = {'Unit': [1, 1, 1, 1, 2, 2, 2, 3, 4, 5, 6, 6, 6, 6], 'Year': [2014, 2015, 2016, 2017, 2015, 2016, 2017, 2017, 2014, 2015, 2014, 2015, 2016, 2017], 'col3' : col3, 'col4' : col4, 'Ratio1' : col5, 'Ratio2' : col6, 'Ratio2' : col6, 'Ratio3' : col7, 'Ratio4' : col8}
df = pd.DataFrame(data=df)
df = df.groupby(['Unit', 'Year']).sum()

df

В этом df я хочу сделать выбор для строк, которые имеют только 0 или 1 значения в столбцах отношения, должен получить проход в качестве комментария. И строки, которые содержат в одном из столбцов отношения какую-то другую запись (какой бы она ни была), должны получить комментарий об ошибке.

Я пытаюсь это так:

[((df_bk_t['Ratio1'] == float(0)) | (df_bk_t['Ratio1'] == float(1))) 
& ((df_bk_t['Ratio2'] == float(0)) | (df_bk_t['Ratio2'] == float(1))) 
& ((df_bk_t['Ratio3'] == float(0)) | (df_bk_t['Ratio3'] == float(1))) 
& ((df_bk_t['Ratio4'] == float(0)) | (df_bk_t['Ratio4'] == float(1)))]

Но этот метод кажется очень неэффективным, когда я должен был бы сделать это для 67 столбцов. Кто-нибудь знает, как это можно сделать более эффективно? И как я могу сделать новый столбец с пропуском или неудачей, основываясь на этом? Правильно ли этот метод для этого?

Заранее спасибо за помощь / предложения,

Джен

Ответы [ 2 ]

4 голосов
/ 20 июня 2019

Одним из подходов может быть определение пользовательского словаря сопоставления, чтобы map строк, где записи all равны 0 или 1, что можетпроверить с помощью isin:

d = {True:'Pass', False:'Fail'}
df['out'] = df.filter(like='Ratio').isin([0,1]).all(1).map(d)

            col3  col4  Ratio1  Ratio2  Ratio3  Ratio4  out
Unit Year                                                  
1    2014     0     0     1.0     0.0     0.0     1.0  Pass
     2015     0     0     0.0     5.0     0.0     1.0  Fail
     2016     0     0     0.0     0.0     0.0     1.0  Pass
     2017     0     0     0.0     0.0     0.0     1.0  Pass
2    2015     2     4     1.0     0.0     1.0     5.0  Fail
     2016     4     6     1.0     1.0     0.0     0.0  Pass
     2017     6     8     1.0     1.0     0.0     0.0  Pass
3    2017     0     0     0.0     0.0     5.0     5.0  Fail
4    2014     0     0     0.0     1.0     1.0     0.0  Pass
5    2015     0     0     0.0     0.0     1.0     1.0  Pass
6    2014   100   200     5.0     0.0     1.0     0.0  Fail
     2015   200   900     1.0     0.0     0.0     1.0  Pass
     2016   300   400     5.0     1.0     5.0     1.0  Fail
     2017   400   500     1.0     1.0     0.0     5.0  Fail
2 голосов
/ 20 июня 2019

Используйте DataFrame.filter для столбцов с именем столбца с Ratio, создайте логический DataFrame с помощью DataFrame.isin и проверьте, все ли значения True в строке с помощью DataFrame.all, последние значения новых столбцов устанавливаются на numpy.where:

df['new'] = np.where(df.filter(like='Ratio').isin([0,1]).all(axis=1), 'Fail', 'Pass')

Если важна производительность, используйте решение numpy:

arr = df.filter(like='Ratio').values
df['new'] = np.where(np.all(np.isin(arr, [0,1]), axis=1), 'Fail', 'Pass')

print (df)

Unit Year                                                  
1    2014     0     0     1.0     1.0     0.0     5.0  Pass
     2015     0     0     1.0     0.0     1.0     1.0  Fail
     2016     0     0     1.0     5.0     1.0     0.0  Pass
     2017     0     0     0.0     1.0     1.0     5.0  Pass
2    2015     2     4     5.0     0.0     0.0     1.0  Pass
     2016     4     6     1.0     1.0     1.0     5.0  Pass
     2017     6     8     0.0     1.0     5.0     5.0  Pass
3    2017     0     0     0.0     0.0     0.0     5.0  Pass
4    2014     0     0     0.0     1.0     0.0     1.0  Fail
5    2015     0     0     1.0     1.0     5.0     1.0  Pass
6    2014   100   200     0.0     5.0     0.0     0.0  Pass
     2015   200   900     0.0     1.0     1.0     1.0  Fail
     2016   300   400     5.0     1.0     1.0     0.0  Pass
     2017   400   500     0.0     0.0     1.0     0.0  Fail
...