我正在尝试创建一个函数,该函数在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秒内运行。有趣的是看到两者之间的区别!
答案 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