Python 在引用其他行上的数据时,如何对DF中的每一行执行计算?

Python 在引用其他行上的数据时,如何对DF中的每一行执行计算?,python,pandas,dataframe,Python,Pandas,Dataframe,我正在寻找一种高效的方法来计算新的列数据(对于每一行),使用其他行上可能存在的信息 这里是示例性子集: 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: '

我正在寻找一种高效的方法来计算新的列数据(对于每一行),使用其他行上可能存在的信息

这里是示例性子集:

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}})
具体来说,我想为每个修改序列(基本上是每行)的“未修改分数”计算新列,然后将其扩展到多个“区域”列

fracumpd=(1-(面积(已修改)/面积(已修改+面积(未修改)))

“area\u unmodified”值必须来自不同的行,因此我似乎无法找到使用类似
df.concat()
df.insert()
这样的函数来实现这一点的方法。 正确的“area_unmodified”值是从共享相同的“baseSeq”和“charge”值的行中确定的,但没有任何修改(为了方便起见,我包括了一列“modType”)

我不必为未修改的行计算fracumpd,但我不想从结果输出中删除这些行(保留它们只会给出fracumpd=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()))))
这是可行的,但对于我的完整数据集(650行表示“行”循环通过,10列表示“X”循环通过),这需要很长时间(~10分钟)

我还提出了令人讨厌的“SettingWithCopyWarning”——我是否可以通过在最后一行的“链式赋值”后面添加
.ascopy()
来避免这种情况?我一直没能弄明白

我已经读过好几遍了,只要有可能就应该避免循环,所以我猜这就是问题所在。 有没有更干净、更快的方法

“modSeq”和“charge”的每一个组合都是唯一的,所以我可能想使用
df.groupby()
df.merge()
,并使用临时df


我经常遇到这种情况,所以我想学习如何在不使用循环的情况下做这类事情(或者至少提高速度)。

如果我们创建一些临时列,就可以对数学运算进行矢量化,这将大大减少时间。之后,我们可以删除临时列

使用您给出的示例,它如下所示:

  • 我们从一个类似如下的
    df
    开始:
  • 创建所有“区域”列的列表:

    area\u cols=df.columns[df.columns.str.contains('area')].tolist()

  • 以下5行代码创建一个临时df,其中包含每个
    baseSeq
    /
    charge
    组合的未修改区域:

  • 以下是此时临时df的外观:

                    unmod_area_0    unmod_area_25   unmod_area_50
    baseSeq  charge         
    ADTPICR       2        22737            30966          24660
    AVALFAED      2        21962            34387          29860
                  3        21885            35444          33511
                  4         2116             3072           2974
    
  • 然后,我们将这个临时数据框连接回主数据框,以便为每个
    baseSeq
    /
    charge
    组合显示适当数量的未修改区域:

    df=df.join(temp_-df,on=['baseSeq','charge'])

  • 此时,我们的数据框架如下所示:

  • 现在进入主要部分:我们在每个“面积”列上循环并计算所需的分数。此计算是跨列的每一行进行矢量化的,应该会大大加快速度
  • 为了清理问题,让我们先删除显示未添加区域的临时列,然后删除临时数据框

    df=df.drop(['unmd'+c表示区域列中的c],轴=1)

    del(临时测向)

    最后的数据帧如下所示:

  • 这与原始嵌套for循环生成的输出相同。但希望能快得多

        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
    
    temp_df = df[['baseSeq'] + ['charge'] + ['modType'] + area_cols].groupby(['baseSeq', 'charge', 'modType'], axis=0).sum()
    temp_df = temp_df.reset_index(level=2)
    temp_df = temp_df[temp_df['modType'] == 'UNMOD']
    temp_df = temp_df.drop('modType', axis=1)
    temp_df.rename(columns = lambda x: 'unmod_' + x, inplace=True)
    
                    unmod_area_0    unmod_area_25   unmod_area_50
    baseSeq  charge         
    ADTPICR       2        22737            30966          24660
    AVALFAED      2        21962            34387          29860
                  3        21885            35444          33511
                  4         2116             3072           2974
    
        baseSeq     modSeq       charge  modType    area_0  area_25 area_50 unmod_area_0    unmod_area_25   unmod_area_50
    0   ADTPICR     ADT[+16]PICR      2  hydoxy       1862     2472    3015        22737            30966           24660
    1   ADTPICR     ADTPICR           2  UNMOD       22737    30966   24660        22737            30966           24660
    2   AVALFAED    AVALFAED[+16]     2  hydroxy     40060     2423    3553        21962            34387           29860
    3   AVALFAED    AVALFAE[+16]D     2  hydroxy     40131     2407    3577        21962            34387           29860
    4   AVALFAED    AVALFAED          2  UNMOD       21962    34387   29860        21962            34387           29860
    5   AVALFAED    AVALFAED[-30]     3  decarbox       12       16      40        21885            35444           33511
    6   AVALFAED    AVALFAED          3  UNMOD       21885    35444   33511        21885            35444           33511
    7   AVALFAED    AVALFAED          4  UNMOD        2116     3072    2974         2116             3072            2974
    
    for col in area_cols:
        num = col.split('_')[1]
        df['fracUnmod_' + num] = 1 - (df[col] / (df[col] + df['unmod_' + col]))
    
        baseSeq     modSeq       charge  modType    area_0  area_25 area_50 fracUnmod_0  fracUnmod_25   fracUnmod_50
    0   ADTPICR     ADT[+16]PICR      2  hydoxy       1862     2472    3015    0.924306      0.926072       0.891057
    1   ADTPICR     ADTPICR           2  UNMOD       22737    30966   24660    0.500000      0.500000       0.500000
    2   AVALFAED    AVALFAED[+16]     2  hydroxy     40060     2423    3553    0.354100      0.934175       0.893664
    3   AVALFAED    AVALFAE[+16]D     2  hydroxy     40131     2407    3577    0.353695      0.934582       0.893023
    4   AVALFAED    AVALFAED          2  UNMOD       21962    34387   29860    0.500000      0.500000       0.500000
    5   AVALFAED    AVALFAED[-30]     3  decarbox       12       16      40    0.999452      0.999549       0.998808
    6   AVALFAED    AVALFAED          3  UNMOD       21885    35444   33511    0.500000      0.500000       0.500000
    7   AVALFAED    AVALFAED          4  UNMOD        2116     3072    2974    0.500000      0.500000       0.500000