Log*_*vis 5 python numpy pandas
我有一个带条件列A和数字列B的Pandas DataFrame.
A B
1 'foo' 1.2
2 'bar' 1.3
3 'foo' 2.2
Run Code Online (Sandbox Code Playgroud)
我还有一个Python字典,它定义了B的范围,它表示给定每个A值的"成功".
mydict = {'foo': [1, 2], 'bar': [2, 3]}
Run Code Online (Sandbox Code Playgroud)
我想在数据框中创建一个新列'error'.它应该描述B的值落在A的可接受范围之外多远.如果A在该范围内,则该值应为零.
A B error
1 'foo' 1.2 0
2 'bar' 1.3 -0.7
3 'foo' 2.2 0.2
Run Code Online (Sandbox Code Playgroud)
我不是一个完整的Pandas/Numpy新手,而且我在Python方面还不错,但事实证明这有点困难.我不想用iterrows()来做这件事,因为我明白它的计算成本很高,而且这会被调用很多.
我最终通过将lambda函数pandas.DataFrame.map()和嵌套的numpy.where()s与可选的x和y输入的给定值相结合来找出解决方案.
getmin = lambda x: mydict[x][0]
getmax = lambda x: mydict[x][1]
df['error'] = np.where(df.B < dtfr.A.map(getmin),
df.B - df.A.map(getmin),
np.where(df.B > df.A.map(getmax),
df.B - df.A.map(getmax),
0
)
)
Run Code Online (Sandbox Code Playgroud)
它有效,但这不可能是最好的方法,对吗?我觉得我在滥用numpy.where(),不知道如何以非迭代的方式将数据帧的多个列中的值映射到lambda函数.(也是为了避免写出轻微粗糙的lambda函数).
我想有三个问题.
有关如何映射多个列的问题,请执行此操作
DataFrame.apply( , axis =1)
Run Code Online (Sandbox Code Playgroud)
对于你的问题,我认为你不需要这个,但我认为如果你通过几个步骤进行计算就更清楚了:
df['low'] = df.A.map(lambda x: mydict[x][0])
df['high'] = df.A.map(lambda x: mydict[x][1])
df['error'] = np.maximum(df.B - df.high, 0) + np.minimum(df.B - df.low, 0)
df
A B low high error
1 foo 1.2 1 2 0.0
2 bar 1.3 2 3 -0.7
3 foo 2.2 1 2 0.2
Run Code Online (Sandbox Code Playgroud)
我相信下面的代码可以说更具可读性。
df['min'] = df.A.apply(lambda x: min(mydict[x]))
df['max'] = df.A.apply(lambda x: max(mydict[x]))
df['error'] = 0.
df.loc[df.B.gt(df['max']), 'error'] = df.B - df['max']
df.loc[df.B.lt(df['min']), 'error'] = df.B - df['min']
df.drop(['min', 'max'], axis=1, inplace=True)
>>> df
A B error
1 foo 1.2 0.0
2 bar 1.3 -0.7
3 foo 2.2 0.2
Run Code Online (Sandbox Code Playgroud)
我不明白为什么你不能使用 numpy.where() 进行三条件数组操作,但你确实牺牲了简单性。
| 归档时间: |
|
| 查看次数: |
4405 次 |
| 最近记录: |