Как сравнить два кадра данных по значениям и заголовкам столбцов в Pandas?

Я хочу добавить столбцы со значениями для указанных списков выборок в один df (df_sets) в соответствии с заголовками столбцов из второго df (df_counts), в зависимости от параметра gene_id, и вычислить среднее значение.

Небольшая часть моих входных данных:

import pandas as pd

d_sets = {'gene_id': ['g0', 'g2', 'g3'], 
          'set_1': [['P1-12', 'P1-25', 'P1-28',], ['P1-6', 'P1-12', 'P1-25'], ['P1-6', 'P1-25', 'P1-28']]}
df_sets = pd.DataFrame.from_dict(data=d_sets)

d_counts = {'gene_id': ['g0', 'g1', 'g2', 'g3'],
            'P1-6': [1, 2, 5, 7],
            'P1-12': [2, 4, 6, 5],
            'P1-25': [5, 1, 2, 6],
            'P1-28': [3, 8, 1, 2]}
df_counts = pd.DataFrame.from_dict(data=d_counts)

Я начал с разделения списков образцов на отдельные столбцы и объединения dfs в gene_id:

df_sets[['1_1', '1_2', '1_3']] = pd.DataFrame(df_sets.set_1.tolist(), index=df_sets.index)
df_merged = df_sets.merge(df_counts, on='gene_id')

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

  gene_id                  set_1    1_1    1_2    1_3  P1-6  P1-12  P1-25  P1-28
0      g0  [P1-12, P1-25, P1-28]  P1-12  P1-25  P1-28     1      2      5      3
1      g2   [P1-6, P1-12, P1-25]   P1-6  P1-12  P1-25     5      6      2      1
2      g3   [P1-6, P1-25, P1-28]   P1-6  P1-25  P1-28     7      5      6      2

но я понятия не имею, как сделать шаг вперед, или, может быть, это неправильный способ достижения желаемого результата:

  gene_id                  set_1   P1-6  P1-12  P1-25  P1-28  mean_set_1
0      g0  [P1-12, P1-25, P1-28]    NaN      2      5      3      3.3333
1      g2   [P1-6, P1-12, P1-25]      5      6      2    NaN      4.3333
2      g3   [P1-6, P1-25, P1-28]      7    NaN      6      2         5.0
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Вот один из подходов:

out = df_sets.merge(df_counts, on='gene_id', how='left')

m = out['set_1'].str.join('|').str.get_dummies().astype(bool)

out.loc[:, m.columns] = out.loc[:, m.columns].where(m)

out['mean_set_1'] = out.loc[:, m.columns].mean(axis=1)

Выход:

  gene_id                  set_1  P1-6  P1-12  P1-25  P1-28  mean_set_1
0      g0  [P1-12, P1-25, P1-28]   NaN    2.0      5    3.0    3.333333
1      g2   [P1-6, P1-12, P1-25]   5.0    6.0      2    NaN    4.333333
2      g3   [P1-6, P1-25, P1-28]   7.0    NaN      6    2.0    5.000000

Объяснение / Промежуточные продукты

m

   P1-12  P1-25  P1-28   P1-6 # note that col order is (probably) not yet correct!
0   True   True   True  False
1   True   True  False   True
2  False   True   True   True

(Если производительность вызывает беспокойство, проверьте здесь, чтобы найти альтернативные методы для этого шага.)

  • Используйте df.loc + df.where, чтобы заменить значения на NaN где False.
  • Добавьте среднее значение по строкам с помощью df.mean на axis=1.

Н.Б. Если вы рискуете, что set_1 не будет соответствовать одному или нескольким столбцам 'P1-*', обязательно используйте df.reindex. Например. предположим, мы имеем:

d_counts = {'gene_id': ['g0', 'g1', 'g2', 'g3'],
            'P1-6': [1, 2, 5, 7],
            'P1-12': [2, 4, 6, 5],
            'P1-25': [5, 1, 2, 6],
            'P1-28': [3, 8, 1, 2],
            'P1-30': [3, 8, 1, 2], # < not present in `set_1`
            }
df_counts = pd.DataFrame.from_dict(data=d_counts)

Тогда вы можете добавить:

# ...

m = out['set_1'].str.join('|').str.get_dummies().astype(bool)
m = m.reindex(df_counts.columns[1:], axis=1)

# ...

Очень хороший ответ. Если имеется много дублирующихся Gene_id, возможно, было бы более эффективно сначала сгенерировать фиктивные значения для уникальных значений, присутствующих в двух входных данных, а затем выполнить слияние.

mozway 20.08.2024 15:45

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