我有两个 Dataframe dfSpecs和dfData。dfSpecs包含dfData中参数列的规格限制。(LSL =规格下限,USL =规格上限)dfSpecs中的参数行不必与dfData中的参数列顺序相同。
dfSpecs = pd.DataFrame(
{'param': ['parameter1', 'parameter2', 'parameter3'],
'LSL': [0, 10, 200],
'USL': [1, 20, 300]}
)
print(dfSpecs)
Output:
param LSL USL
0 parameter1 0 1
1 parameter2 10 20
2 parameter3 200 300
dfData = pd.DataFrame(
{'id': ['foo', 'foo', 'bar', 'bar'],
'x': [1, 1, 1, 1],
'y': [1, 2, 1, 2],
'parameter1': [0.5, 0.6, 1.8, 0.4],
'parameter2': [12, 14, 21, 15],
'parameter3': [199, 301, 256, 234]}
)
print(dfData)
Output:
id x y parameter1 parameter2 parameter3
0 foo 1 1 0.5 12 199
1 foo 1 2 0.6 14 301
2 bar 1 1 1.8 21 256
3 bar 1 2 0.4 15 234
现在,我想获得一个新的 Dataframe ,其中包含超出参数和id规范限制的行数。
预期输出如下所示:
id param fail_count
0 foo parameter1 0
1 foo parameter2 0
2 foo parameter3 2
3 bar parameter1 1
4 bar parameter2 1
5 bar parameter3 0
以下代码可以工作,但速度非常慢(最多几分钟,取决于 Dataframe 大小):
fails=[]
for id, df in dfData.groupby('id'):
for i, spec in dfSpecs.iterrows():
fail_count = len(df[spec['param']].loc[(df[spec['param']]<spec['LSL']) | (df[spec['param']]>spec['USL'])])
fails.append(id, [spec['param'], fail_count])
dfFails = pd.DataFrame(fails, columns=['id','parameter','fail_count'])
- 有没有更简单、更快的方法来实现这一点?**我想在Pandas身上有更好的方法。
编辑:改写并添加示例输出
3条答案
按热度按时间2izufjch1#
感谢您的回复,根据您的编辑,我建议如下:
cygmwpex2#
首先,您可以对
dfData
Dataframe 执行melt
操作,然后使用dfSpecs
查找transform
中的left、right,以便与pd.Series.between
一起使用,并将其作为新列fail_count
与assign
一起分配,然后将groupby.sum()
与id
、param
一起分配,以获得计数。或者你可以这样做(我觉得它比上面更有效):
或者,如果你认为融化很慢,你可以尝试堆叠,虽然我怀疑有多大区别。
iqxoj9l93#
最后,我使用panda的
gt
和lt
函数提出了自己的工作解决方案,首先循环遍历按id列分组的dfData
Dataframe ,然后选择感兴趣的列(这里手动地,但是可以用真实的数据集上的.loc[]
来完成)来自dfData
)并对一系列dfSpecs['USL']
和dfSpecs['LSL']
使用gt
和lt
函数,其中'param'
位于索引中,sum
位于结果中。这给出了没有id
列的pd.Series
,因此我需要手动将它们和ffill()
连接起来。第一行包含id
和NaN
,因此我删除了该行。由于参数仍在索引中,因此我重置了索引以将param
返回到 Dataframe 中。当然,我不得不对每个循环的结果进行concat
,最后我重命名了列,因为它们在过程之后没有合理的名称。问题中的代码在我的数据集上使用了
25.6s
。此代码仅使用了5.8s