修改pandas数据框中的行的子集

假设我有一个有两列A和B的pandas DataFrame。我想修改这个DataFrame(或者创build一个副本),这样,当A为0时,B总是NaN。我将如何实现?

我尝试了以下

df['A'==0]['B'] = np.nan 

 df['A'==0]['B'].values.fill(np.nan) 

没有成功。

尝试这个:

 df.ix[df.A==0, 'B'] = np.nan 

df.A==0expression式创build一个索引行的布尔序列, 'B'select列。 您也可以使用它来转换列的子集,例如:

 df.ix[df.A==0, 'B'] = df.ix[df.A==0, 'B'] / 2 

我不太了解大pandas的内部结构,知道它的工作原理,但基本问题是,有时在DataFrame中build立索引会返回结果的副本,有时会返回原始对象的视图。 根据这里的文档,这种行为取决于底层的numpy行为。 我发现在一个操作中(而不是[一个] [两个])访问所有内容更有可能用于设置。


更新

ix已弃用,请使用.loc作为基于标签的索引

 df.loc[df.A==0, 'B'] = np.nan 

这里是从高级索引pandas文档:

该部分将准确解释您的需求! 原来df.loc (因为.ix已被弃用 – 正如下面的许多人所指出的那样)可以用于dataframe的冷切片/切片。 和。 它也可以用来设置的东西。

 df.loc[selection criteria, columns I want] = value 

所以Bren的回答是“find我所有df.A == 0的地方,selectB列并将其设置为np.nan '

从pandas开始0.20 ix已被弃用 。 正确的方法是使用loc

这里是一个工作的例子

 >>> import pandas as pd >>> import numpy as np >>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB')) >>> df.loc[df.A == 0, 'B'] = np.nan >>> df AB 0 0 NaN 1 1 0 2 0 NaN >>> 

说明:

正如在这里的文档中所解释的, .loc 主要是基于标签的,但是也可以与布尔数组一起使用

所以,我们上面正在做的是应用df.loc[row_index, column_index]

  • 利用loc可以将一个布尔数组作为一个掩码,告诉pandas我们要在row_index更改哪个子集的行
  • 利用事实loc也是使用column_index的标签'B'select列的标签column_index

我们可以使用逻辑,条件或任何返回一系列布尔值来构造布尔数组的操作。 在上面的例子中,我们希望任何包含0 rows ,因为我们可以使用df.A == 0 ,正如您在下面的示例中所看到的,这将返回一系列布尔值。

 >>> df = pd.DataFrame({"A":[0,1,0], "B":[2,0,5]}, columns=list('AB')) >>> df AB 0 0 2 1 1 0 2 0 5 >>> df.A == 0 0 True 1 False 2 True Name: A, dtype: bool >>> 

然后,我们使用上面的布尔数组来select和修改必要的行:

 >>> df.loc[df.A == 0, 'B'] = np.nan >>> df AB 0 0 NaN 1 1 0 2 0 NaN 

有关更多信息,请在此处查看高级索引文档。

为了大幅提高速度,请使用NumPy的where函数。

build立

使用一些零创build一个包含100,000行的两列DataFrame。

 df = pd.DataFrame(np.random.randint(0,3, (100000,2)), columns=list('ab')) 

numpy.where快速解决scheme

 df['b'] = np.where(df.a.values == 0, np.nan, df.b.values) 

计时

 %timeit df['b'] = np.where(df.a.values == 0, np.nan, df.b.values) 685 µs ± 6.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each) %timeit df.loc[df['a'] == 0, 'b'] = np.nan 3.11 ms ± 17.2 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) 

Numpy的速度快了四倍

使用.valuesreplace多个列转换为numpy数组:

 df.loc[df.A==0, ['B', 'C']] = df.loc[df.A==0, ['B', 'C']].values / 2