Я ищу эффективный способ вычисления новых данных столбца (для каждой строки), используя информацию, которая может присутствовать в какой-то другой строке.
Вот примерное подмножество:
df = pd.DataFrame({'baseSeq': {0: 'ADTPICR', 1: 'ADTPICR', 2: 'AVALFAED', 3: 'AVALFAED', 4: 'AVALFAED', 5: 'AVALFAED', 6: 'AVALFAED', 7: 'AVALFAED'}, 'modSeq': {0: 'ADT[+16]PICR', 1: 'ADTPICR', 2: 'AVALFAED[+16]', 3: 'AVALFAE[+16]D', 4: 'AVALFAED', 5: 'AVALFAED[-30]', 6: 'AVALFAED', 7: 'AVALFAED'}, 'charge': {0: 2, 1: 2, 2: 2, 3: 2, 4: 2, 5: 3, 6: 3, 7: 4}, 'modType': {0: 'hydoxy', 1: 'UNMOD', 2: 'hydroxy', 3: 'hydroxy', 4: 'UNMOD', 5: 'decarbox', 6: 'UNMOD', 7: 'UNMOD'}, 'area_0': {0: 1862, 1: 22737, 2: 40060, 3: 40131, 4: 21962, 5: 12, 6: 21885, 7: 2116}, 'area_25': {0: 2472, 1: 30966, 2: 2423, 3: 2407, 4: 34387, 5: 16, 6: 35444, 7: 3072}, 'area_50': {0: 3015, 1: 24660, 2: 3553, 3: 3577, 4: 29860, 5: 40, 6: 33511, 7: 2974}})
baseSeq modSeq charge modType area_0 area_25 area_50
0 ADTPICR ADT[+16]PICR 2 hydoxy 1862 2472 3015
1 ADTPICR ADTPICR 2 UNMOD 22737 30966 24660
2 AVALFAED AVALFAED[+16] 2 hydroxy 40060 2423 3553
3 AVALFAED AVALFAE[+16]D 2 hydroxy 40131 2407 3577
4 AVALFAED AVALFAED 2 UNMOD 21962 34387 29860
5 AVALFAED AVALFAED[-30] 3 decarbox 12 16 40
6 AVALFAED AVALFAED 3 UNMOD 21885 35444 33511
7 AVALFAED AVALFAED 4 UNMOD 2116 3072 2974
В частности, я хочу вычислить новые столбцы для «немодифицированной дроби» каждой модифицированной последовательности (по существу, каждой строки), а затем расширить ее на несколько столбцов «области».
fracUnmod = (1- (area_modified / (area_modified + area_unmodified)))
Значения "area_unmodified" должны поступать из разных строк, поэтому я не могу придумать, как это сделать, используя такую функцию, как df.concat()
или df.insert()
.
Правильные значения "area_unmodified" определяются из строки, которая разделяет те же значения 'baseSeq' и 'charge', но без каких-либо изменений (для удобства я включил столбец 'modType').
Мне не нужно вычислять fracUnmod для неизмененных строк, но я не хочу удалять эти строки из полученного результата (оставляя их просто, получаем fracUnmod = 0.5, что нормально).
Иногда встречаются строки, в которых не найдено неизмененных версий (не показаны), но я их пропустил, так как мне известно, что я задаю второстепенные вопросы в отдельном сообщении, плюс я смог отфильтровать их вручную в Excel.
Я делал что-то вроде этого, проходя по каждой строке:
for X in df.columns[df.columns.str.contains('area')].tolist():
df[X.replace('area', 'fracUnmod')] = ''
for row in df.index:
for X in df.columns[df.columns.str.contains('area')].tolist():
Y = X.replace('area', 'fracUnmod')
df[Y].iloc[row] = (1 - ((df.iloc[row][X]) / ((df.iloc[row][X]) + (df[(df.baseSeq==df.iloc[row].baseSeq) & (df.charge==df.iloc[row].charge) & (df.baseSeq==df.modSeq)][X].item()))))
Это работает, но это занимает много времени (~ 10 минут) для моего полного набора данных (650 строк для "строки" для цикла, 10 столбцов "области" для "X" для цикла).
Я также поднимаю этот надоедливый «SettingWithCopyWarning» - можно ли этого избежать, добавив .ascopy()
к «Цепочечному назначению» моей последней строки? Я никогда не мог понять это.
Я несколько раз читал, что по возможности следует избегать циклов, поэтому я предполагаю, что это проблема.
Есть ли более чистый и быстрый способ сделать это?
Каждая комбинация 'modSeq' и 'charge' уникальна, поэтому, возможно, я захочу сделать что-нибудь с df.groupby()
или df.merge()
и использовать временный DF?
Я часто сталкиваюсь с этой ситуацией, поэтому я стремлюсь узнать, как я могу делать такие вещи без использования петель (или, по крайней мере, увеличения скорости).