修改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==0
expression式创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的速度快了四倍
使用.values
replace多个列转换为numpy数组:
df.loc[df.A==0, ['B', 'C']] = df.loc[df.A==0, ['B', 'C']].values / 2