如何使 pd.Dataframe 列分配更快?
How to make pd.Dataframe column assignment faster?
因此,我正在尝试将列添加到现有数据框中,主要是进行逻辑比较:
def qualitycheck(data, qparams, qid):
data = data.assign(parameter_set = qid)
data = data.assign(volume_below_max = (data["volume"] < int(qparams["max_volume"])))
data = data.assign(volume_trucks_below_max = (data["volume_trucks"] < int(qparams["max_volume_trucks"])))
data = data.assign(volume_cars_below_max = (data["volume_cars"] < int(qparams["max_volume_cars"])))
data = data.assign(volume_diffcheck_ok = diffcheck(data["volume"]))
data = data.assign(occupancy_below_max = data["occupancy"] < int(qparams["max_occupancy"]))
data = data.assign(occupancy_diffcheck_ok = diffcheck(data["occupancy"]))
data = data.assign(speed_below_max = data["speed"] < int(qparams["max_speed"]))
data = data.assign(speed_trucks_below_max= data["speed_trucks"] < int(qparams["max_speed_trucks"]))
data = data.assign(speed_cars_below_max = data["speed_cars"] < int(qparams["max_speed_cars"]))
data = data.assign(speed_diffcheck_ok = diffcheck(data["speed"]))
data = data.assign(volume_speed_plausible = q_v_plaus(data["volume"], data["speed"]))
data = data.assign(net_time_gap_below_max = data["net_time_gap"] < 60)
data = data.assign(speed_occupancy_plausible = v_occ_plaus(data["speed"], data["occupancy"], qparams))
return data
这些 .assigns 中使用的三个函数也只是提供的两列的一些逻辑比较。 'qparams' 是一个 DataFrame,其中一行包含一些常量。每次调用这个 qualitycheck()-Function 时,都会传入一个 5 行的数据框,然后将其扩展为这 14 列并返回。使用 %timeit 我得到这个函数的时间为 11.9ms。问题是,我必须调用它大约 2500 万次,这会导致像 83h。
那么有什么方法可以提高这个功能的性能吗?
编辑:这是三个函数:
def diffcheck(column):
if column.sum() == 0:
return True
val0 = column.iloc[0]
check = val0 == column
if check.sum() < len(check):
return True
else:
return False
def q_v_plaus(qs,vs):
plaus = []
for i in range(0,5):
q = qs.iloc[i]
v = vs.iloc[i]
if q == 0 and v > 0:
plaus.append(False)
elif q > 0 and v == 0:
plaus.append(False)
else:
plaus.append(True)
return plaus
主要问题是您为 5 行块调用此函数,更好的性能应该为 1k、10k 行块。
函数 DataFrame.assign
有点慢,但主要问题应该出在您的自定义函数 diffcheck
、q_v_plaus
、v_occ_plaus
- 我想没有向量化(如果可能的话)不看是不可能说不出来的)。
移除 assign
并比较 .values
以将 Series
替换为 1d numpy array
:
def qualitycheck(data, qparams, qid):
data['parameter_set'] = qid
data['volume_below_max'] = data["volume"].values < int(qparams["max_volume"])
...
...
我尝试优化你的功能:
def diffcheck(column):
if column.values.sum() == 0:
return True
val0 = column.iat[0]
check = val0 == column
return check.values.sum() < len(check)
函数适用于所有行,而不仅仅是前 5 行:
def q_v_plaus1(qs,vs):
qs = qs.values
vs= vs.values
m1 = (qs== 0) & (vs > 0)
m2 = (qs> 0) & (vs == 0)
return ~(m1 | m2)
被重写为更快的替代方案:
def q_v_plaus1(qs,vs):
qs = qs.values
vs= vs.values
m1 = (qs!= 0) | (vs <= 0)
m2 = (qs<= 0) | (vs != 0)
return m1 & m2
因此,我正在尝试将列添加到现有数据框中,主要是进行逻辑比较:
def qualitycheck(data, qparams, qid):
data = data.assign(parameter_set = qid)
data = data.assign(volume_below_max = (data["volume"] < int(qparams["max_volume"])))
data = data.assign(volume_trucks_below_max = (data["volume_trucks"] < int(qparams["max_volume_trucks"])))
data = data.assign(volume_cars_below_max = (data["volume_cars"] < int(qparams["max_volume_cars"])))
data = data.assign(volume_diffcheck_ok = diffcheck(data["volume"]))
data = data.assign(occupancy_below_max = data["occupancy"] < int(qparams["max_occupancy"]))
data = data.assign(occupancy_diffcheck_ok = diffcheck(data["occupancy"]))
data = data.assign(speed_below_max = data["speed"] < int(qparams["max_speed"]))
data = data.assign(speed_trucks_below_max= data["speed_trucks"] < int(qparams["max_speed_trucks"]))
data = data.assign(speed_cars_below_max = data["speed_cars"] < int(qparams["max_speed_cars"]))
data = data.assign(speed_diffcheck_ok = diffcheck(data["speed"]))
data = data.assign(volume_speed_plausible = q_v_plaus(data["volume"], data["speed"]))
data = data.assign(net_time_gap_below_max = data["net_time_gap"] < 60)
data = data.assign(speed_occupancy_plausible = v_occ_plaus(data["speed"], data["occupancy"], qparams))
return data
这些 .assigns 中使用的三个函数也只是提供的两列的一些逻辑比较。 'qparams' 是一个 DataFrame,其中一行包含一些常量。每次调用这个 qualitycheck()-Function 时,都会传入一个 5 行的数据框,然后将其扩展为这 14 列并返回。使用 %timeit 我得到这个函数的时间为 11.9ms。问题是,我必须调用它大约 2500 万次,这会导致像 83h。
那么有什么方法可以提高这个功能的性能吗?
编辑:这是三个函数:
def diffcheck(column):
if column.sum() == 0:
return True
val0 = column.iloc[0]
check = val0 == column
if check.sum() < len(check):
return True
else:
return False
def q_v_plaus(qs,vs):
plaus = []
for i in range(0,5):
q = qs.iloc[i]
v = vs.iloc[i]
if q == 0 and v > 0:
plaus.append(False)
elif q > 0 and v == 0:
plaus.append(False)
else:
plaus.append(True)
return plaus
主要问题是您为 5 行块调用此函数,更好的性能应该为 1k、10k 行块。
函数 DataFrame.assign
有点慢,但主要问题应该出在您的自定义函数 diffcheck
、q_v_plaus
、v_occ_plaus
- 我想没有向量化(如果可能的话)不看是不可能说不出来的)。
移除 assign
并比较 .values
以将 Series
替换为 1d numpy array
:
def qualitycheck(data, qparams, qid):
data['parameter_set'] = qid
data['volume_below_max'] = data["volume"].values < int(qparams["max_volume"])
...
...
我尝试优化你的功能:
def diffcheck(column):
if column.values.sum() == 0:
return True
val0 = column.iat[0]
check = val0 == column
return check.values.sum() < len(check)
函数适用于所有行,而不仅仅是前 5 行:
def q_v_plaus1(qs,vs):
qs = qs.values
vs= vs.values
m1 = (qs== 0) & (vs > 0)
m2 = (qs> 0) & (vs == 0)
return ~(m1 | m2)
被重写为更快的替代方案:
def q_v_plaus1(qs,vs):
qs = qs.values
vs= vs.values
m1 = (qs!= 0) | (vs <= 0)
m2 = (qs<= 0) | (vs != 0)
return m1 & m2