Python:numpy/pandas 根据条件更改值
Posted
技术标签:
【中文标题】Python:numpy/pandas 根据条件更改值【英文标题】:Python: numpy/pandas change values on condition 【发布时间】:2014-10-09 04:51:58 【问题描述】:我想知道是否有更快、更“pythonic”的方式来执行以下操作,例如使用一些内置方法。 给定一个 pandas DataFrame 或 numpy 浮点数组,如果该值等于或小于 0.5,我需要计算倒数并乘以 -1 并用新计算的值替换旧值。 “变换”可能是一个不好的词选择,如果你有更好/更准确的描述,请告诉我。
感谢您的帮助和支持!!
数据:
import numpy as np
import pandas as pd
dicti = "A" : np.arange(0.0, 3, 0.1),
"B" : np.arange(0, 30, 1),
"C" : list("ELVISLIVES")*3
df = pd.DataFrame(dicti)
我的功能:
def transform_colname(df, colname):
series = df[colname]
newval_list = []
for val in series:
if val <= 0.5:
newval = (1/val)*-1
newval_list.append(newval)
else:
newval_list.append(val)
df[colname] = newval_list
return df
函数调用:
transform_colname(df, colname="A")
**--> 我在这里总结一下结果,因为 cmets 不允许发布代码(或者我不知道该怎么做)。**
感谢大家快速而精彩的回答!
将 ipython "%timeit" 与“真实”数据一起使用:
我的职能: 10 个循环,3 个循环中的最佳:每个循环 24.1 毫秒
来自 jojo:
def transform_colname_v2(df, colname):
series = df[colname]
df[colname] = np.where(series <= 0.5, 1/series*-1, series)
return df
100 个循环,3 个循环中的最佳:每个循环 2.76 毫秒
来自 FooBar:
def transform_colname_v3(df, colname):
df.loc[df[colname] <= 0.5, colname] = - 1 / df[colname][df[colname] <= 0.5]
return df
100 次循环,3 次中的最佳:每个循环 3.32 毫秒
来自 dmvianna:
def transform_colname_v4(df, colname):
df[colname] = df[colname].where(df[colname] <= 0.5, (1/df[colname])*-1)
return df
100 个循环,3 个循环中的最佳:每个循环 3.7 毫秒
请告诉/告诉我您是否会以不同的方式实现您的代码!
最后一个问题:(已回答) "FooBar" 和 "dmvianna" 的版本如何成为“通用”?我的意思是,我必须将列的名称写入函数(因为将其用作变量不起作用)。请解释最后一点! --> 谢谢jojo,“.loc”不是正确的方法,但非常简单的 df[colname] 就足够了。将上述功能更改为更“通用”。 (也将“>”更改为“
非常感谢!!
【问题讨论】:
@jojo:谢谢!!您的解决方案更 Pythonic,但速度较慢。我的功能:10000 个循环,最好的 3 个:每个循环 164 µs。您的版本:1000 个循环,最好的 3 个:每个循环 395 µs。 您的速度测试结果如何?很难比 numpy 快……至少在 python 中。 ;) @tryptofame 只是尝试使用非平凡大小的框架进行基准测试,下面的两个解决方案都会快得多) 【参考方案1】:如 @jojo 的回答,但使用熊猫:
df.A = df.A.where(df.A > 0.5, (1/df.A)*-1)
或
df.A.where(df.A > 0.5, (1/df.A)*-1, inplace=True) # this should be faster
.where 文档字符串:
定义:df.A.where(self, cond, other=nan, inplace=False, 轴=无,级别=无,try_cast=False,raise_on_error=True)
文档字符串: 返回一个与 self 形状相同的对象及其对应的条目 来自自我,其中 cond 为 True,否则来自其他。
【讨论】:
仅供参考,Dataframe 不是 np.ndarray 的子类(也从未如此),尽管它确实像二维 ndarray。 谢谢@Jeff,我一定是跳过了历史课。由于它的行为,我确实假设了这一点。 pandas 似乎与 numpy 非常兼容。【参考方案2】:如果我们谈论的是数组:
import numpy as np
a = np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6], dtype=np.float)
print 1 / a[a <= 0.5] * (-1)
不过,这只会返回小于0.5
的值。
或者使用np.where
:
import numpy as np
a = np.array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6], dtype=np.float)
print np.where(a < 0.5, 1 / a * (-1), a)
谈pandas
DataFrame:
正如 @dmvianna 的回答(所以给他一些信任;)),将其改编为pd.DataFrame
:
df.a = df.a.where(df.a > 0.5, (1 / df.a) * (-1))
【讨论】:
呵呵,.head() 只会返回 5 个左右的元素...我用它来测试样本。 ;7)【参考方案3】:典型的技巧是编写一个通用的数学运算来应用于整个列,然后使用指标来选择我们实际应用它的行:
df.loc[df.A < 0.5, 'A'] = - 1 / df.A[df.A < 0.5]
In[13]: df
Out[13]:
A B C
0 -inf 0 E
1 -10.000000 1 L
2 -5.000000 2 V
3 -3.333333 3 I
4 -2.500000 4 S
5 0.500000 5 L
6 0.600000 6 I
7 0.700000 7 V
8 0.800000 8 E
9 0.900000 9 S
10 1.000000 10 E
11 1.100000 11 L
12 1.200000 12 V
13 1.300000 13 I
14 1.400000 14 S
15 1.500000 15 L
16 1.600000 16 I
17 1.700000 17 V
18 1.800000 18 E
19 1.900000 19 S
20 2.000000 20 E
21 2.100000 21 L
22 2.200000 22 V
23 2.300000 23 I
24 2.400000 24 S
25 2.500000 25 L
26 2.600000 26 I
27 2.700000 27 V
28 2.800000 28 E
29 2.900000 29 S
【讨论】:
不要链接索引,使用df.loc[..., ...] = value
!
是的。在我的辩护中,这是假期后的第一天:)以上是关于Python:numpy/pandas 根据条件更改值的主要内容,如果未能解决你的问题,请参考以下文章
如何在 python+numpy/pandas 中使用二值化在 json 文件中创建新列
Python 中的二阶导数 - scipy/numpy/pandas
使用 numpy / pandas 读取 Python 中 CSV 文件的最后 N 行