簡體   English   中英

根據Python Pandas中的條件減去兩行

[英]Subtract two rows based on condition in Python Pandas

我正在使用一個數據集,我有時間和幾種不同種類的微生物的濃度重復,所以它只是一個時間列和一堆數字為了這個問題。 我每兩個小時進行一次測量,有時我會連續進行兩次測量,這些測量的時間戳會非常相似。 對於那些類似的時間戳,我想取所有列的兩行的平均值,並將這些平均值返回到之前放置兩個值的新數據幀。

這是數據框的樣子。 時間戳已轉換為數值,因為相對時間/日期無關緊要。 你可以看到我正在談論的一個例子,在第9和第10個索引有兩個非常相似的時間

      Time        A1       A2       A3
 0    0.000069    118.0    108.0    70.0
 1    0.087049    189.0    54.0     89.0
 2    0.156551    154.0    122.0    107.0
 3    0.721516    129.0    148.0    148.0
 4    0.789329    143.0    162.0    212.0
 5    0.882743    227.0    229.0    149.0
 6    0.964907    208.0    255.0    241.0
 7    1.041424    200.0    241.0    222.0
 8    1.731806    733.0    838.0    825.0
 9    1.794340    804.0    996.0    954.0
10    1.794769    861.0    987.0    1138.0

將時間列中的數字四舍五入到一個合理的值似乎是顯而易見的,我可以使用groupby()函數(如果我實際上需要對它們進行分組)然后平均“重復”值,但我已經下了一個新的哲學之路,我想用pandas iterrows()函數來遍歷行,逐個1,並比較每兩個連續的行並對它們應用一個條件來實現相同的結果。 我已經到達了這樣的東西,它沒有錯誤代碼,但似乎沒有做任何事情。

for i, row in df.iterrows():
    row2 = row + 1 #I feel like this line is the crux of the problem
    if row2.Time - row.Time >= 0.1:
        row = (row2 + row)/2
    else:
        row = row

出於好奇,我很想知道哪個更快,分組和平均方式或for循環和平均方式。 也許有一個漂亮的lamba函數方式來做到這一點? 我已經廣泛搜索過這種類型的東西,我很想知道你們都能想出什么。

干杯

以下是一些一般提示:

  • 首選python for循環的矢量化計算。 例如,調用df['Time'].diff()比在循環中計算row2['Time'] - row1['Time']要快得多。 對於足夠大的N ,向量化計算將總是超過for循環計算,其中Nfor-loop所需的迭代次數。
  • 優先選擇基於行的操作的基於列的操作
  • 與較小陣列上的許多操作相比,在大型陣列上的操作更少。

作為原理的演示,請考慮這兩種計算所需結果的不同方法:

import numpy as np
import pandas as pd

df = pd.DataFrame({'A1': [118.0, 189.0, 154.0, 129.0, 143.0, 227.0, 208.0, 200.0, 733.0, 804.0, 861.0], 'A2': [108.0, 54.0, 122.0, 148.0, 162.0, 229.0, 255.0, 241.0, 838.0, 996.0, 987.0], 'A3': [70.0, 89.0, 107.0, 148.0, 212.0, 149.0, 241.0, 222.0, 825.0, 954.0, 1138.0], 'Time': [6.8999999999999997e-05, 0.087049000000000001, 0.156551, 0.72151599999999994, 0.78932899999999995, 0.88274300000000006, 0.96490699999999996, 1.0414239999999999, 1.7318060000000002, 1.79434, 1.7947689999999998]}) 

def using_loop(df):
    for i in range(len(df)-1):
        row1, row2 = df.iloc[i], df.iloc[i+1]
        if row2['Time'] - row1['Time'] >= 0.1:
            df.iloc[i] = (row2 + row1)/2
    return df

def using_column_based_operations(df):
    mask = df['Time'].diff() >= 0.1
    prior = mask.shift(-1).fillna(False)
    df.loc[prior] = (df.loc[mask].values+df.loc[prior].values)/2
    return df

In [220]: using_loop(df).equals(using_column_based_operations(df))
Out[220]: True

下面是一個使用IPython的的基准%%timeit函數,它顯示using_column_based_operations是數千倍的速度比using_loopnrows是10 ** 4。 隨着nrows增加, using_column_based_operations的速度優勢using_column_based_operations增加。

In [216]: nrows, ncols = 10**4, 4

In [217]: %%timeit df = pd.DataFrame(np.random.random((nrows, ncols)), columns=['Time', 'A1', 'A2', 'A3'])
   .....: using_loop(df)
   .....: 
1 loop, best of 3: 3.02 s per loop

In [218]: %%timeit df = pd.DataFrame(np.random.random((nrows, ncols)), columns=['Time', 'A1', 'A2', 'A3'])
   .....: using_column_based_operations(df)
   .....: 
1000 loops, best of 3: 1.91 ms per loop

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM