2016-11-11 8 views
1

У меня есть dataframe, в котором есть образец столбца, содержащий повторяющиеся образцы (заканчивающиеся на _2) и один и тот же столбец, который описывает исходный образец. Новая категория содержит мутационный тип, в котором патогенный/вероятный патогенный организм является наиболее разрушительным, а вероятность того, что доброкачественность является наименее опасной. Ниже приведена сокращенная/базовая версия моего фреймворка.Условно удаление строк не работает в соответствии с назначением в pandas

df = pd.DataFrame(columns=['Sample', 'same','New Category'], 
      data=[ 
        ['HG_12_34', 'HG_12_34', 'Pathogenic/Likely Pathogenic'], 
        ['HG_12_34_2', 'HG_12_34', 'Likely Benign'], 
        ['KD_89_9', 'KD_89_9', 'Likely Benign'], 
        ['KD_98_9_2', 'KD_89_9', 'Likely Benign'], 
        ['LG_3_45', 'LG_3_45', 'Likely Benign'], 
        ['LG_3_45_2', 'LG_3_45', 'VUS'] 
        ]) 

Я хочу условно удалить либо образец или его дубликат в зависимости от которых одна имеет наименьшее повреждающее мутацию в новой категории, т.е. если один образец, скорее всего, доброкачественные и дубликат имеет Патогенные/Likley Патогенные вариант, то я хотите удалить/удалить строку образца.

Я попытался это, передав dataframe функции, которая возвращает список индексов, которые представляют строки, которые будут удалены, и я впоследствии их бросил.

def get_unwanted_duplicates_ix(df): 

    # filter df for samples that have a duplicate 
    same_only = df.groupby("same").filter(lambda x: len(x) > 1) 

    list_index_to_delete = [] 


    for num in range(0,same_only.shape[0]-1): 

     row1 = same_only.irow(num) 
     row2 = same_only.irow(num+1) 
     index = list(same_only.index.values)[num] 



     if row1['Sample']+"_2" == row2['Sample'] or \ 
      row1['Sample'] == row2['Sample']+"_2": 

      if row1['New Category'] == row2['New Category']: 
       list_index_to_delete.append(index+1) 

      elif row1['New Category'] == "Pathogenic/Likely Pathogenic" \ 
       and row2['New Category'] != "Pathogenic/Likely Pathogenic": 
       list_index_to_delete.append(index+1) 

      elif row2['New Category'] == "Pathogenic/Likely Pathogenic" \ 
       and row1['New Category'] != "Pathogenic/Likely Pathogenic": 
       list_index_to_delete.append(index) 

      elif row1['New Category'] == "VUS" \ 
       and row2['New Category'] != "VUS": 
       list_index_to_delete.append(index+1) 

      elif row2['New Category'] == "VUS" \ 
       and row1['New Category'] != "VUS": 
       list_index_to_delete.append(index) 

      elif row1['New Category'] == 'Likely Benign' \ 
       and row2['New Category'] == 'Likely Benign': 
       list_index_to_delete.append(index+1) 

      else: 
       list_index_to_delete.append(index+1) 

    return list_index_to_delete 

unwanted = get_unwanted_duplicates_ix(df) 
df = df.drop(df.index[unwanted]) 

Эта функция является беспорядком и, что неудивительно, не функционирует так, как я надеялся. Наилучшей оценкой будет точка в правильном направлении.

ответ

2

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

df['New Category code'] = df['New Category'].replace(
    {'Likely Benign': 1, 'VUS': 2, 'Pathogenic/Likely Pathogenic': 3}) 

Следующая команда зависит от того, хотите ли вы сохранить несколько строк с одинаковой степенью серьезности. Если да, то группа по same колонке и выберите строку с кодом макс тяжести:

df[df.groupby('same')['New Category code'].transform(max) == df['New Category code']]     

     Sample  same     New Category New Category code 
0 HG_12_34 HG_12_34 Pathogenic/Likely Pathogenic     3 
2 KD_89_9 KD_89_9     Likely Benign     1 
3 KD_98_9_2 KD_89_9     Likely Benign     1 
5 LG_3_45_2 LG_3_45       VUS     2 

Если нет (всегда держать только одну строку в каждой группе), то вместо того, чтобы сортировать значения в порядке возрастания тяжести и взять последний (спасибо @JonClements за идею):

df.sort_values('New Category code').groupby('same').last() 

      Sample     New Category New Category code 
same                 
HG_12_34 HG_12_34 Pathogenic/Likely Pathogenic     3 
KD_89_9 KD_98_9_2     Likely Benign     1 
LG_3_45 LG_3_45_2       VUS     2 
+0

Это то, что вы хотите, или хотите группировать не по тому же столбцу? Если нет, добавьте желаемый результат в вопрос. –

+1

Я бы предположил, что вместо того, чтобы преобразовывать и сравнивать максимальные значения (которые для групп с более чем одним максимальным значением возвращают несколько выборок), сортируйте по коду вашей новой категории, а затем примените 'groupby ('same'). First () 'вместо ... (или сортировать по возрастанию, тогда примените' .last() '- в зависимости от того, что вам интересно) –

+0

@JonClements Спасибо, я обновил ответ. –