使用pandas将数据分组到不同的批次中

时间:2014-01-17 13:57:54

标签: python pandas

我正在尝试创建一个函数,该函数在DataFrame上添加一列,为一组时间数据创建批号。我假设一旦水平低于/高于1000我们已经清空(然后重新填充)批次,因此它是一个新的批次。这意味着我可以按批号对数据进行分组,以进行进一步分析。

我的数据看起来像

df_test = pd.DataFrame(
{ 'Time'  : [1300, 1400, 1500, 1600, 1700, 1800],
  'Level' : [ 200, 1300, 1500,  200, 1500, 1400],
  'Data'  : range(6) })

   Data  Level  Time
0     0    200  1300
1     1   1300  1400
2     2   1500  1500
3     3    200  1600
4     4   1500  1700
5     5   1400  1800

我希望它看起来像是:

   Batch  Data  Level  Time
0    NaN     0    200  1300
1      1     1   1300  1400
2      1     2   1500  1500
3    NaN     3    200  1600
4      2     4   1500  1700
5      2     5   1400  1800

我并不担心批次之间的批号会发生什么。 NaN似乎是一个明智的选择,但任何事情都是分开的和不同的。

到目前为止,我已经尝试过:

df['inUse'] = df['Level'] > 1000

然后尝试找出如何为列编号并开始一个新的数字,但不能弄清楚如何。任何帮助,将不胜感激!感谢。

修改

尝试:

df['Batch'] = (df['Level'] < 1000).cumsum()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\alarr\Python\WinPython-64bit-2.7.5.3\python-2.7.5.amd64\lib\site-packages\pandas\core\series.py", line 1662, in cumsum
    np.putmask(result, mask, pa.NA)
ValueError: cannot convert float NaN to integer

还使用python 2.7.5和pandas 0.12.0。另外值得一提的是,我想将此应用于最多100万行的数据集。忘了提这个!

解决:

我在我的主数据集上尝试了两个答案,两者都有效!谢谢。出于好奇,我将时间和时间都计算在0.016秒,而计数器在0.156秒内运行。有趣的是看到两者之间的区别!

2 个答案:

答案 0 :(得分:2)

这应该适用于0.13或更高版本的pandas:

import pandas as pd
df = pd.DataFrame({ 'Time'  : [1300, 1400, 1500, 1600, 1700, 1800],
                    'Level' : [ 200, 1300, 1500,  200, 1500, 1400],
                    'Data'  : range(6) })
df['Batch'] = (df['Level'] < 1000).cumsum()
print(df)

产量

   Data  Level  Time  Batch
0     0    200  1300      1
1     1   1300  1400      1
2     2   1500  1500      1
3     3    200  1600      2
4     4   1500  1700      2
5     5   1400  1800      2

如果您希望批次之间有NaN,那么您可以这样做:

import pandas as pd
import numpy as np
df = pd.DataFrame({ 'Time'  : [1300, 1400, 1500, 1600, 1700, 1800],
                    'Level' : [ 200, 1300, 1500,  200, 1500, 1400],
                    'Data'  : range(6) })

mask = df['Level'] < 1000
df['Batch'] = mask.cumsum()
df.ix[mask, 'Batch'] = np.nan
print(df)

产生

   Data  Level  Time  Batch
0     0    200  1300    NaN
1     1   1300  1400      1
2     2   1500  1500      1
3     3    200  1600    NaN
4     4   1500  1700      2
5     5   1400  1800      2

修改:对于Pandas版本0.12或更早版本there was an issue与在布尔系列上使用cumsum相关。这可能是您看到的错误的来源。在这种情况下,请尝试在应用int之前将掩码转换为d cumsum

mask = (df['Level'] < 1000)
df['Batch'] = mask.astype('int').cumsum()
df.ix[mask, 'Batch'] = np.nan

答案 1 :(得分:0)

如果你很乐意使用全局变量,你可以这样做。

df = pd.DataFrame({ 'Time'  : [1300, 1400, 1500, 1600, 1700, 1800],
                    'Level' : [ 200, 1300, 1500,  200, 1500, 1400],
                    'Data'  : range(6) })
counter = 0
def handler(x):
    global counter
    if x>1000: return counter
    counter += 1
    return float('nan')

df['Batch'] = df.Level.apply(handler)
print df