pandas 计算单格数值的区间,代码如何更高效

原始数据:有一列名称为【时长】,描述了1-100s的时间长度,类型为float 

需求内容:再增加一列【时长区间】,用于描述【时长】列每个单元格值的区间,结果样式如下

      时长    时长区间

0  3.498   [3,4)

1  0.535   (0,1)

2  2.355   [2,3)

3  6.541   [5,8)

4  8.508  [8,10)

 

现有的代码,当【时长】只有几百或几千行时,执行速度还是挺快的。但实际【时长】数据多达20-50万行,执行时间会非常非常长

import pandas as pd
import time

dict = {
    "时长": {
        0: 3.498,
        1: 0.535,
        2: 2.355,
        3: 6.541,
        4: 8.508,
        5: 0.391,
        6: 1.254,
        7: 0.276,
        8: 12.14,
        9: 0.827,
        10: 1.996,
    }
}

df = pd.DataFrame(dict)
df["时长区间"] = 0

time_s = time.perf_counter()

for x, y in enumerate(df["时长"]):
    if y < 1:
        df.iloc[[x], [1]] = "(0,1)"
    elif y < 2:
        df.iloc[[x], [1]] = "[1,2)"
    elif y < 3:
        df.iloc[[x], [1]] = "[2,3)"
    elif y < 4:
        df.iloc[[x], [1]] = "[3,4)"
    elif y < 5:
        df.iloc[[x], [1]] = "[4,5)"
    elif y < 8:
        df.iloc[[x], [1]] = "[5,8)"
    elif y < 10:
        df.iloc[[x], [1]] = "[8,10)"
    else:
        df.iloc[[x], [1]] = "[10,~)"

time_e = time.perf_counter()

print(df.head())
print(df.shape)

print("耗时:%s s" % ("%0.2f" % (time_e - time_s)))

 

上述代码是否还有优化的空间,可以让执行速度更快?尤其是【时长】数据多达20-50万行时,谢谢

用pd.cut()方法,代码如下,如果你的对应关系不一样, 可以修改参数list和labels调整

import pandas as pd
import time
dict = {
    "时长": {
        0: 3.498,
        1: 0.535,
        2: 2.355,
        3: 6.541,
        4: 8.508,
        5: 0.391,
        6: 1.254,
        7: 0.276,
        8: 12.14,
        9: 0.827,
        10: 1.996,
    }
}

data = pd.DataFrame(dict)
data['时长区间'] = pd.cut(data['时长'],
                      [0,1,2,3,4,5,8,10,100],  # 数值区间
                      labels = ['(0-1)','[1,2)','[2,3)','[3,4)','[4,5)','[5,8)','[8,10)','[10,~)'], # 标签
                      right=False)

 

没看懂你的时长和区间是怎么个映射关系。不过可以先把时长这一列保存到list中,全部处理完之后再并到detaform中,这样子只要操作一次,速度应该会快很多。

import numpy as np

data['四舍五入时长'] = np.int32(data['时长'])
#以此类推
data['时长区间'] = None
data.loc[data['四舍五入时长']==0,'时长区间'] = '(0,1)'
data.loc[data['四舍五入时长']==1,'时长区间'] = '[1,2)'