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)

pandasDataFrame

正如 @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 numpy pandas

Python 中的二阶导数 - scipy/numpy/pandas

使用 numpy / pandas 读取 Python 中 CSV 文件的最后 N 行

使用 numpy / pandas 读取 Python 中 CSV 文件的最后 N 行

python数据分析模块:numpy、pandas全解