首页 > 解决方案 > Pandas 按列和掩码索引

问题描述

我有以下数据框:

import numpy as np
import pandas as pd


np.random.seed(398)

df = pd.DataFrame(np.random.randn(20, 3), columns=['a', 'b', 'c'])

我希望使用以下索引按列和行值索引数据框:

row_indexer = (df.index > 5)
col_indexer = (df > -1) & (df < 1)

并修改这些位置的值。因此,基本上数据帧中索引大于 5 且值介于 -1 和 1 之间的所有情况。这可以通过以下方式完成:

df[row_indexer[:, None] & col_indexer] = np.nan

没有问题。但是,我现在想在包含另外 3 个名为["a_str", "b_str", "c_str"]. 请参阅以下内容:

str_cols = [i + "_str" for i in df.columns]
df[str_cols] = 'blank'

并使用与之前的值完全相同的掩码,修改数据框中的所有_str列。因此,使用相同的示例,如果原始数据帧以下列方式修改数字列:

           a         b         c
0  -1.810802 -0.776590 -0.495147
1   1.381038  0.235168  2.334671
2   0.406279 -1.571401  1.011139
3  -1.200217 -1.013983 -0.040659
4   1.261759  0.863896  0.228914
5   0.696952 -1.384910  1.204492
6        NaN  1.180030       NaN
7  -2.027946       NaN       NaN
8        NaN       NaN       NaN
9        NaN       NaN       NaN
10 -1.389175  2.263662       NaN
11       NaN -1.077414       NaN
12       NaN -1.696859 -1.049889
13 -1.057308       NaN       NaN
14       NaN       NaN -1.206815
15       NaN       NaN       NaN
16  2.063715 -1.981503       NaN
17       NaN -1.022833  1.957646
18  1.315031       NaN  1.425088
19 -1.860641       NaN       NaN

然后字符串列将如下所示:

         a_str       b_str       c_str
0        blank       blank       blank
1        blank       blank       blank
2        blank       blank       blank
3        blank       blank       blank
4        blank       blank       blank
5        blank       blank       blank
6   new string       blank  new string
7        blank  new string  new string
8   new string  new string  new string
9   new string  new string  new string
10       blank       blank  new string
11  new string       blank  new string
12  new string       blank       blank
13       blank  new string  new string
14  new string  new string       blank
15  new string  new string  new string
16       blank       blank  new string
17  new string       blank       blank
18       blank  new string       blank
19       blank  new string  new string

问题是我不知道如何在原始数据帧上执行此操作,我只能在副本上执行此操作:

x = row_indexer[:, None] & col_indexer
x.columns = [i + "_str" for i in x.columns]

a = df[['a_str', 'b_str', 'c_str']]
a[x] = 'new string'

重现此内容的完整代码如下:

import numpy as np
import pandas as pd


np.random.seed(398)

df = pd.DataFrame(np.random.randn(20, 3), columns=['a', 'b', 'c'])

row_indexer = (df.index > 5)
col_indexer = (df > -1) & (df < 1)
x = row_indexer[:, None] & col_indexer
df[row_indexer[:, None] & col_indexer] = np.nan
print(df)
str_cols = [i + "_str" for i in df.columns]
df[str_cols] = 'blank'

x.columns = [i + "_str" for i in x.columns]

a = df[['a_str', 'b_str', 'c_str']]
a[x] = 'new string'
print(a)

编辑:

想补充一点,这在技术上可以通过以下方式解决:

df[str_cols] = a

但是,这意味着需要将内存加倍作为原始数据帧的副本,理想情况下我希望避免这种情况。我很确定内存已经因为掩码(df[row_indexer[:, None] & col_indexer)而增加了一倍,所以我想尽可能避免内存爆炸

标签: pythonpandasdataframenumpy

解决方案


在这种情况下采取的基本方法是创建一个布尔掩码并将此掩码的视图作为numpy数组获取,然后选择mask您希望替换值的列

mask = row_indexer[:, None] & col_indexer
df[str_cols] = df[str_cols].mask(mask.values, 'new string')

为什么使用mask.values而不是mask

由于 pandas 会根据索引对齐数据,因此列的名称mask必须与 的名称匹配,str_cols才能使 mask 方法正常工作。要解决这个问题,有两个选项,要么重命名 mask 对应的列str_cols,另一个选项是创建一个 mask 视图作为 numpy 数组(因为 numpy 数组没有命名信息),因此索引对齐不再是问题和面具会正常工作。


           a         b         c       a_str       b_str       c_str
0  -1.810802 -0.776590 -0.495147       blank       blank       blank
1   1.381038  0.235168  2.334671       blank       blank       blank
2   0.406279 -1.571401  1.011139       blank       blank       blank
3  -1.200217 -1.013983 -0.040659       blank       blank       blank
4   1.261759  0.863896  0.228914       blank       blank       blank
5   0.696952 -1.384910  1.204492       blank       blank       blank
6        NaN  1.180030       NaN  new string       blank  new string
7  -2.027946       NaN       NaN       blank  new string  new string
8        NaN       NaN       NaN  new string  new string  new string
9        NaN       NaN       NaN  new string  new string  new string
10 -1.389175  2.263662       NaN       blank       blank  new string
11       NaN -1.077414       NaN  new string       blank  new string
12       NaN -1.696859 -1.049889  new string       blank       blank
13 -1.057308       NaN       NaN       blank  new string  new string
14       NaN       NaN -1.206815  new string  new string       blank
15       NaN       NaN       NaN  new string  new string  new string
16  2.063715 -1.981503       NaN       blank       blank  new string
17       NaN -1.022833  1.957646  new string       blank       blank
18  1.315031       NaN  1.425088       blank  new string       blank
19 -1.860641       NaN       NaN       blank  new string  new string

推荐阅读