#python #python-3.x #pandas #dataframe
#python #python-3.x #pandas #dataframe
Вопрос:
Мне понадобится помощь, чтобы добавить новые столбцы в зависимости от условий и другого фрейма данных. Я знаю, что сложность высока, но я попытался добавить как можно больше примеров, которые я мог, и исправить простой алгоритм, чтобы делать то, что мне нужно.
Вот основной фрейм данных, в который мы будем добавлять столбцы :
df1
Name start1 end1 strand length
OK0100087.1 187 250 63
OK0100087.1 830 750 - 80
OK0100087.1 500 625 125
OK0100087.1 375 275 - 100
OK0100087.1 150 20 - 120
OK0100088.1 600 1000 400
из этого df я хотел бы добавить 2 столбца с именем Newstart
и `Newend` `
df2
Name start1 end1 strand length Newstart Newend
OK0100087.1 187 250 63
OK0100087.1 830 750 - 80
OK0100087.1 500 625 125
OK0100087.1 375 275 - 100
OK0100087.1 150 20 - 120
OK0100088.1 600 1000 400
и для заполнения пустых ячеек мы будем использовать другой df, такой как :
df2
Name start_plus end_plus start_minus end_minus
OK0100087.1_0 0 375 1000 625
OK0100087.1_1 376 750 624 250
OK0100087.1_3 751 1000 249 0
OK0100088.1 0 12000 0 12000
OK0100089.1_0 0 566 3000 2433
OK0100089.1_1 567 3000 2432 0
идея состоит в том, чтобы для каждой строки проверять значение цепочки, а затем выполнять алгоритм, такой как :
if df1.strand.eq("-"):
df1.Newstart = df1.start1 - df2.end_minus
df1.Newend = df1.Newstart - df1.length
if df1.strand.eq(" "):
df1.Newstart = df1.start1 - df2.start_plus
df1.Newend = df1.Newstart df1.length
итак, давайте возьмем в качестве примера, чтобы лучше понять:
первая Name
группа OK0100087.1 в df1
Name start1 end1 strand length Newstart Newend
OK0100087.1 187 250 63
OK0100087.1 830 750 - 80
OK0100087.1 500 625 125
OK0100087.1 375 275 - 100
OK0100087.1 150 20 - 120
первая строка представляет собой
цепочку, затем df1.end1
= 250
в df2 мы сохраняем только df2.Names.str.contains(df1.Name)
значение и 250 находится в пределах интервала
Name start_plus end_plus
OK0100087.1_0 0 375
(Я взял start_plus и end_plus в качестве интервала, потому что это strand).
итак
if df1.strand.eq(" "):
df1.Newstart = df1.start1 - df2.start_plus
(df1.Newstart = 187 - 0 = 187
df1.Newend = df1.Newstart df1.length
(df1.Newend =187 63 = 250)
что дает:
Name start1 end1 strand length Newstart Newend
OK0100087.1 187 250 63 187 250
OK0100087.1 830 750 - 80
OK0100087.1 500 625 125
OK0100087.1 375 275 - 100
OK0100087.1 150 20 - 120
OK0100088.1 500 700 200
теперь давайте сделаем это для второй строки:
strand.eq("-")
, так df1.start1
что (830) находится в пределах интервала :
Name start_minus end_minus
OK0100087.1_0 1000 625
итак
if df1.strand.eq("-"):
df1.Newstart = df1.start1 - df2.end_minus
(df1.Newstart = 830 - 625 =205)
df1.Newend = df1.Newstart - df1.length
df1.Newend = 205 - 80 = 125)
что дает:
Name start1 end1 strand length Newstart Newend
OK0100087.1 187 250 63 187 250
OK0100087.1 830 750 - 80 205 125
OK0100087.1 500 625 125
OK0100087.1 375 275 - 100
OK0100087.1 150 20 - 120
OK0100088.1 500 700 200
и так далее …
Name start1 end1 strand length Newstart Newend
OK0100087.1 187 250 63 187 250
OK0100087.1 830 750 - 80 205 125
OK0100087.1 500 625 125 125 250
OK0100087.1 375 275 - 100 125 25
OK0100087.1 150 20 - 120 150 20
OK0100088.1 600 1000 200 33 433
Если у кого-то есть какая-то идея, как это сделать, это было бы потрясающе.
большое вам спасибо
Ответ №1:
Из вашего примера неясно, уникальны ли имена или нет, и что делать, если какое-то имя из df1 совпадает с несколькими именами из df2.
В любом случае, процедура, которую я бы рекомендовал, — это использование DataFrame.apply
метода. Этот метод получает функцию, которую он будет применять для каждой строки (укажите axis=1 в аргументах, в противном случае значение по умолчанию равно 0) при добавлении нового столбца в каждую строку (ваши атрибуты Newstart и Newend).
Пример:
def func(row-from-df):
df2Portion = d2[d2[Name].str.contains(row-from-df[Name], na=False)] # using vectorize string
if row-from-df.strand.eq(' '):
# your logic here, you can add rows etc..
else:
# your logic here
return row-from-df
df1.apply(func, axis=1)
Обратите внимание, что вы должны вернуть строку, которую вы изменили.
Также обратите внимание, что возвращаемое значение представляет собой новый фрейм данных, он не является inplace, который изменяет исходный df1.
Вы можете прочитать больше здесь