Элементы Vlook Up из другого фрейма данных для создания мультииндексного фрейма данных в Python

Есть 2 фрейма данных и один иерархический индекс (pandas multiIndex). Фрейм данных A имеет список идентификаторов и имен. Фрейм данных B содержит список комбинаций имен и оценку сходства.

Я хочу, основываясь на мультииндексе, взять значения из Dataframe A и проверить, существует ли комбинация в DataFrame B. Если да, я хочу вывести в мой Multindex dataframe оценку сходства, в противном случае просто 0.

DataFrame A (исходный DataFrame)

test= pd.DataFrame({'row':['a','b','c','d'],'col_A' : ["Alexis","Alexi","Peter","Pete"]})

test = test.set_index('row');test
Out:   
    row   col_A   
    a     Alexis
    b     Alexi
    c     Peter
    d     Pete

DataFrame B (сходство имен)

names = pd.DataFrame({'A' : ["Alexis","Alexi","Peter","Pete"]
                    ,'B' : ["Alexi","Alexis","Pete","Peter"]
                    , "similarity" : [0.9,0.9,0.8,0.8]})
Out:
       A       B      similarity
0   Alexis   Alexi         0.9
1   Alexi    Alexis        0.9
2   Peter    Pete          0.8
3   Pete     Peter         0.8

Мультииндекс

# Creating a Pandas MultiIndex 
arrays = [['a', 'a', 'a', 'b', 'b', 'c'],
          ['b', 'c', 'd', 'c', 'd', 'd']]

tuples = list(zip(*arrays))
indexy = pd.MultiIndex.from_tuples(tuples, names=['first', 'second'])

для итерации по индексу я использую приведенную ниже функцию, однако я не уверен, как ее настроить, чтобы получить оценку сходства, если она существует, или 0, когда ее нет.

a = pd.DataFrame((test.reindex(indexy.get_level_values(0)).values (?) test.reindex(indexy.get_level_values(1))).values,index=indexy,columns=test.columns)

Где я хочу выглядеть так:

   row      similarity
first second           
a     b             0.9
      c             0
      d             0
b     c             0
      d             0
c     d             0.8

Вам нужно создать мультииндексный DF по другой причине, чтобы получить ожидаемый результат?

Ben.T 30.04.2018 19:42

Я создаю 3 мультииндексных фрейма данных, которые я объединю позже. Первый datafrme включает сравнение числовых данных (так что разница между сущностями a, bc, d, ...) Второй включает категориальное сравнение, совпадение не совпадает и последнее, где я хочу включить сходство строк на основе значений stting . Позже я буду использовать этот объединенный набор данных в качестве входных данных для алгоритма. Отвечает ли это на ваш вопрос?

A.Papa 01.05.2018 11:25

Да, чтобы получить a, мне было интересно, почему вы использовали мультииндексный df.

Ben.T 01.05.2018 13:29

Вроде я использую иерархическую индексацию, которая является разделом MultiIndex приведенного выше кода. Однако я не уверен, как совместить это с vlookup в таблице оценки сходства. a - это не полностью завершенная команда. Это именно то, о чем я прошу. Как мне правильно закодировать a, чтобы получить желаемый результат.

A.Papa 01.05.2018 15:39
0
4
90
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Итак, если вы не слишком увлечены мультииндексом, вот один из способов получить ваши данные, как вы ожидаете:

import pandas as pd
test= pd.DataFrame({'row':['a','b','c','d'],'col_A' : ["Alexis","Alexi","Peter","Pete"]})
names = pd.DataFrame({'A' : ["Alexis","Alexi","Peter","Pete"],
                    'B' : ["Alexi","Alexis","Pete","Peter"],
                    "similarity" : [0.9,0.9,0.8,0.8]})

Заметьте, я не set_indextest, но вы можете это сделать, это немного изменит следующее (см. Комментарии). Вы можете создать фрейм данных a, например:

import itertools
a = pd.DataFrame([p for p in itertools.combinations(test['col_A'], 2)],columns =['A','B'],
                 index=['%s,%s'%p for p in itertools.combinations(test['row'], r=2)])
# here if you did set_index your test, then replace 
# index=['%s,%s'%p for p in itertools.combinations(test['row'], r=2)] by 
# index=['%s,%s'%p for p in itertools.combinations(test.index, r=2)]

А это выглядит так:

          A      B
a,b  Alexis  Alexi
a,c  Alexis  Peter
a,d  Alexis   Pete
b,c   Alexi  Peter
b,d   Alexi   Pete
c,d   Peter   Pete

Затем вы можете использовать reset_index (чтобы получить текущий индекс в качестве столбца, но это зависит от того, что именно вы хотите) merge с names в столбцах A и B, заполните nan значением 0, отбросьте два столбца A и B и переименуйте (при необходимости) :

a = a.reset_index().merge(names, how = 'left', on = ['A','B']).fillna(0).\
     drop(labels = ['A','B'], axis=1).rename(columns = {'index':'row', 'similarity':'col_A'})

Дай мне знать, сможешь ли ты делать то, что хочешь, после

Обновлено: с новым результатом, который вы ищете, вы можете:

a = pd.DataFrame([p for p in itertools.combinations(test['col_A'], 2)],columns =['A','B'],
                 index=pd.MultiIndex.from_tuples([p for p in itertools.combinations(test.index, r=2)], names=['first', 'second']))

Примечание: itertools генерирует кортежи, которые используются в pd.MultiIndex.from_tuples для определения вашего мультииндексного DF.

Теперь вы можете merge (чтобы сохранить мультииндекс, вам нужно reset_index до и set_index после:

a = a.reset_index().merge(names, how = 'left', on = ['A','B']).fillna(0).\
         drop(labels = ['A','B'], axis=1).set_index(['first', 'second'])

Привет, Бен! Это здорово, но мне нужно, чтобы фрейм данных был с иерархической индексацией. Itertools не удерживают уровень. Можно ли сделать то же самое с использованием иерархического индекса?

A.Papa 02.05.2018 10:36

Я могу заполнить иерархическую таблицу следующим образом: df = pd.DataFrame (index = indexy, columns = ["подобие"]) df ["A"] = test.reindex (indexy.get_level_values ​​(0)). Values ​​df [" B "] = test.reindex (indexy.get_level_values ​​(1)). Values ​​Но как я могу объединить их на основе значений?

A.Papa 02.05.2018 10:48

@ A.Papa Я думаю, что мой EDIT должен делать то, что вы ищете, но если нет, я не уверен, что понимаю, что вы хотите и почему вы хотите использовать test.reindex(indexy.get_level_values(0)).values. Надеюсь, это все равно поможет :)

Ben.T 02.05.2018 15:21

Я обновил свой вопрос. В конце мне нужен иерархический фрейм данных. Это означает двухуровневые индексы. Мне не обязательно использовать этот test.reindex(indexy.get_level_values(0)).values только для того, чтобы получить фрейм данных на основе иерархических индексов index.

A.Papa 03.05.2018 12:04

@ A.Papa, если вы попробуете мой вчерашний EDIT, у вас будет иерархический DF

Ben.T 03.05.2018 13:04

Вот и получилось! Спасибо за дальнейшие объяснения!

A.Papa 03.05.2018 16:47

Вот еще один способ сделать это, используя мультииндексы, merge и map:

from itertools import combinations

a = pd.DataFrame(index = pd.MultiIndex.from_tuples(list(combinations(test.col_A,2))))
a = a.merge(names, left_index=True, right_on=['A','B'],how='left').fillna(0)
testmap = test.reset_index().set_index('col_A').squeeze()

a['A'] = a.A.map(testmap)
a['B'] = a.B.map(testmap)
a = a.set_index(['A','B'])
a

Выход:

     similarity
A B            
a b         0.9
  c         0.0
  d         0.0
b c         0.0
  d         0.0
c d         0.8

Подробности

  • Создайте MultiIndex, используя комбинации из itertools
  • Объедините пустой фрейм данных с мультииндексом с фреймом данных 'names' и заполните NaN нулем
  • Используйте set_index, чтобы создать серию для сопоставления col_A со значениями row в тесте

Другие вопросы по теме