根据Python Pandas中的条件减去两行

时间:2016-06-27 01:36:40

标签: python numpy 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乘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循环和平均方式。也许那里有一个漂亮的兰巴 功能方式也这样做?我已经广泛搜索过这种类型的 事情,我很乐意看到你们都能想到的东西。

干杯

1 个答案:

答案 0 :(得分:9)

以下是一些常规提示:

  • 首选python for循环的矢量化计算。例如,调用df['Time'].diff()比在循环中计算row2['Time'] - row1['Time']要快得多。向量化计算将始终超过for循环计算,以获得足够大的N,其中Nfor-loop所需的迭代次数。
  • Prefer column-based operations基于行的操作
  • 在较小阵列上的许多操作中,希望减少对大型阵列的操作。

作为原理的演示,请考虑这两种计算所需结果的不同方法:

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为10 ** 4时,using_loop显示nrowsnrows快数千倍。随着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 的速度优势会增加。

addEventListener