Есть ли эффективный способ одновременной фильтрации данных кластера в большом pandas кадре данных? - PullRequest
0 голосов
/ 13 июля 2020

У меня есть большой pandas фрейм данных, который выглядит следующим образом:

DF:
ID               setID      Weight
PG_002456788.1    1         100
UG_004678935.1    2         110
UG_012975895.1    2         150
PG_023788904.1    3         200
UR_073542247.1    3         200
UR_099876678.2    3         264
PR_066120875.1    4         400
PR_098759678.1    4         600
UR_096677888.2    4         750
PG_012667994.1    5         800
PG_077555239.1    5         800

Я хотел бы отфильтровать строки на основе критериев:

Критерии выбора представителя для каждого setID указаны ниже порядок приоритета

Preference 1 ID starting with PG_
Preference 2 ID starting with UG_
Preference 3 ID starting with PR_
Preference 4 ID starting with UR_

Наряду с этим следующим приоритетом является выбор наивысшего веса одновременно для каждого кластера setID.

'Желаемый результат:'

ID              setID   weight
PG_002456788.1    1      100
UG_012975895.1    2      150
PG_023788904.1    3      200
PR_098759678.1    4      600
PG_012667994.1    5      800

Также , Я хотел бы напечатать строки с тем же идентификатором "Initials", а также весом отдельно, если таковые имеются.

For example,

  ID             setID      weight
 PG_012667994.1    5        800
 PG_077555239.1    5        800

Ответы [ 2 ]

1 голос
/ 13 июля 2020

Для первой части: создайте новый столбец с именем code из идентификатора. Затем отсортируйте фрейм данных по коду и весу, сгруппируйте по setID и возьмите первую запись.

df['code'] = df['ID'].str[:2].replace({'PG': 1, 'UG': 2, 'PR': 3, 'UR': 4})
df2 = df.sort_values(['code', 'Weight'], ascending=[True, False]).groupby('setID').first()
df2 = df2.reset_index().drop('code', axis=1)

Вывод

   setID              ID  Weight
0      1  PG_002456788.1     100
1      2  UG_012975895.1     150
2      3  PG_023788904.1     200
3      4  PR_098759678.1     600
4      5  PG_012667994.1     800

Вторая часть:

df3 = df.join(df.groupby(['setID', 'code']).count()['ID'],
        on=['setID', 'code'], rsuffix='_Count')
df3[ df3['ID_Count'] > 1].drop(['code', 'ID_Count'], axis=1)

Вывод:

                ID  setID  Weight
1   UG_004678935.1      2     110
2   UG_012975895.1      2     150
4   UR_073542247.1      3     200
5   UR_099876678.2      3     264
6   PR_066120875.1      4     400
7   PR_098759678.1      4     600
9   PG_012667994.1      5     800
10  PG_077555239.1      5     800
1 голос
/ 13 июля 2020

IIU C вы можете определить фиктивный столбец pd.Categorical с начальной подстрокой в ​​ID и использовать его и Weight для упорядочивания фрейма данных. Затем groupby setID, возьмите first:

df['ID_init'] = pd.Categorical(df.ID.str.split('_',1).str[0],
                               categories=['PG','UG','PR','UR'],
                               ordered=True)

(df.sort_values(by=['ID_init','Weight'], ascending=[True, False])
   .groupby('setID')
   .head(1)
   .sort_values('setID')
   .drop('ID_init',1))

               ID  setID  Weight
0  PG_002456788.1      1     100
2  UG_012975895.1      2     150
3  PG_023788904.1      3     200
7  PR_098759678.1      4     600
9  PG_012667994.1      5     800
...