根据熊猫中的另一个dafaframe添加两个新列

时间:2020-09-20 17:33:59

标签: 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

所以让我们以一个例子来更好地理解:

df1

中的第一个Name OK0100087.1
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作为间隔,因为它是+链)。

如此

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 个答案:

答案 0 :(得分:1)

从您的示例中还不清楚名称是否唯一,如果df1中的某个名称与df2中的多个名称匹配,该怎么办。

无论如何,我建议的过程是使用DataFrame.apply方法。 Thats方法会收到一个函数,该函数将适用于每行(在args中指定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)

请注意,您必须返回已更改的行。

还请注意,返回值是一个新的DataFrame,不会破坏原始df1。

您可以阅读更多here