Получить строки из одного DF на основе матрицы поиска DF - PullRequest
0 голосов
/ 03 ноября 2019

У меня есть два кадра данных панд. Один (DF1) содержит данные о фактическом «типе» информации в каждом Имени, а второй (DF2) содержит, какой «тип» присутствует в Имени. DF2 не будет содержать все имена из DF1. Необходимо вернуть Dataframe со строками из DF1, которые удовлетворяют из DF2.

Например, DF1:

       Name      type(uuid)           start         letter     etc..
    0  2         a_1                  011           H
    1  2         a_3                  012           I
    2  1         a_2                  203           K
    3  4         a_1                  943           P
    4  5         a_3                  925           L 

DF2 матрица поиска:

       Name      a_1    a_2     a_3    a_n
    0  1         0       1       0      0 
    1  2         1       0       1      0 
    2  3         0       0       0      0 

DF2является матрицей результатов от разделения поезда / теста. Следовательно, не содержит полный набор данных. Основываясь на именах в df, мне нужно выбрать строки из DF1.

Нужно будет вывести фрейм данных.

DF Тип A:

       Name      type           start         letter
    0  2         a_1            011           H
    1  2         a_3            012           I
    2  1         a_2            203           K

Я пытался использоватьмаски для этого. Но это не самый эффективный способ сделать это. Я довольно новичок в использовании панд и чувствую, что есть лучший способ сделать это. Что я пробовал:

type = df_two.columns.values

for name in df_two.index.tolist():
    mask = df_one.type.apply(lambda x: any(item for item in type if item in x))

    mask_doc = (df_one['Name'].values == name) & (mask)

    temp = df_one[mask_doc]

Это дает мне отдельный фрейм данных для каждого Имени, и я должен объединить их позже. Это довольно медленно.

Есть ли лучший / эффективный подход для этого в пандах?

Редактировать: Значения a_1, .., a_n на самом деле равны uuid в моем наборе данных.

Редактировать2: пытался обобщить вопрос слишком много. Вычистил до насущной проблемы.

Ответы [ 2 ]

0 голосов
/ 03 ноября 2019

Я бы сделал это:

Сначала создайте Dataframe для использования DataFrame.lookup с DataFrame.reset_index

df2_mapper=df2.set_index('Name')

затем сопоставьте, используя DataFrame.lookup, чтобы создать дополнительный столбец с примерно 1 и 0. Затем просто выберите только строки со значением 1

df_filter=df1.copy()
df_filter['filter']=df2_mapper.lookup(df1['Name'],df1['type'])
df_filter=df_filter[df_filter['filter'].eq(1)]
print(df_filter)
   Name type  start letter  filter
0     2  a_1     11      H       1
1     2  a_3     12      I       1
2     1  a_2    203      K       1
3     2  b_1    943      P       1
4     5  b_3    925      L       1

Наконец я подумал, что тамможет быть более двух типов, и поэтому я решил предложить вам создать словарь данных. Где каждый фрейм данных соответствует типу.

groups=df_filter['type'].str.replace('(\d+)','').str.replace('_','')
df_types={i:group.reindex(columns=df1.columns) for i, group in df_filter.groupby(groups)}

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

for _type in df_types:
    print(f'df_types[{_type}]')
    print(df_types[_type])
    print('-'*20)

Вывод

df_types[a]
   Name type  start letter
0     2  a_1     11      H
1     2  a_3     12      I
2     1  a_2    203      K
--------------------
df_types[b]
   Name type  start letter
3     2  b_1    943      P
4     5  b_3    925      L
--------------------

если число типов только два, вы можете просто сделать:

# Creanting mapper
df2_mapper=df2.set_index('Name')
#Mapping and filtering
df_filter=df1.copy()
df_filter['filter']=df2_mapper.lookup(df1['Name'],df1['type'])
df_filter=df_filter[df_filter['filter'].eq(1)]
#Creating df_A and df_B
mask_A=df_filter['type'].str.contains('a')
df_type=df_filter.reindex(columns=df1.columns)
df_A=df_type[mask_A]
df_B=df_type[~mask_A]
0 голосов
/ 03 ноября 2019

Если поиск действительно необходим, тогда вы можете использовать unstack для получения многоиндексированного элемента. Затем, отфильтровав и присоединив правой кнопкой мыши df1 к unstacked df2, вы получите результат.

result = pd.merge(pd.DataFrame(df2.unstack()), df1, left_index=True, right_on=['type', 'name'], how='left')

Затем выберите нужные столбцы.

...