Как получить столбцы, содержащие имена предопределенных классов эквивалентности значений в каждой строке кадра данных Pandas? - PullRequest
2 голосов
/ 04 августа 2020
# import package
import pandas as pd

Проблема

У меня есть фрейм данных:

data = {'row1': ['a', 'A', 'B', 'b'],
        'row2': ['a', 'b', 'c', 'd'],
        'row3': ['a', 'b', 'd', 'D']}
df = pd.DataFrame.from_dict(data, orient='index', columns=['col'+str(x) for x in range(4)])

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

enter image description here

I also have a list of equivalence classes. Each equivalence class consists of items which are taken as equivalent.

equivalenceClasses={'classA':['a','A'],
                    'classB':['b','B'],
                    'classC':['c','C'],
                    'classD':['d','D']}

I would like to create a dataframe in which the rows in the above dataframe are replaced by the names of the equivalence classes the letters in the row belong to. (Each equivalence class should appear no more than once in a row, and we should use NaNs to post-pad rows in which not all columns are fille by a name of an equivalence class). Ie I want this output:

enter image description here


My method

I achieve the goal by:

def differentClasses(colvalues):
    return list(set([equivalenceClassName for colvalue in colvalues
                                          for equivalenceClassName, equivalenceClass in zip(equivalenceClasses.keys(),
                                                                                   equivalenceClasses.values())
                                          if colvalue in equivalenceClass]))

( Понимание списка, при понимании вложенного списка .)

df['classes'] = df.apply(lambda row : differentClasses(row['col'+str(x)] for x in range(4)), axis = 1) 

(Под влиянием this .)

df в этот момент выглядит так :

введите описание изображения здесь

Fini sh by:

result_df = pd.DataFrame(df['classes'].tolist(),index=df.index,columns=['classcol'+str(x) for x in range(4)])

result_df - желаемый результат выше.

Вопрос

Есть ли более стандартный способ сделать это? Что-то вроде:

df.equivalenceClassify(equivalenceClassList)

и я получаю свой результат?

1 Ответ

2 голосов
/ 04 августа 2020

Нам нужно создать новый dict на основе вашего исходного equivalenceClasses, затем просто выполните replace

from collections import ChainMap
d = dict(ChainMap(*[dict.fromkeys(y,x) for x , y in equivalenceClasses.items()]))
df = df.replace(d)
Out[299]: 
        col0    col1    col2    col3
row1  classA  classA  classB  classB
row2  classA  classB  classC  classD
row3  classA  classB  classD  classD

Затем

df = df.mask(df.apply(pd.Series.duplicated,1))
Out[307]: 
        col0    col1    col2    col3
row1  classA     NaN  classB     NaN
row2  classA  classB  classC  classD
row3  classA  classB  classD     NaN
...