更改pandas数据帧中预先选定元素的列

nun*_*usa 4 python dataframe pandas

我们有一个包含三个不同列的数据框,如上例(df)所示.此任务的目标是每次第1列中的字母更改时,用np.nan 替换第2列的第一个元素.由于研究中的数据库非常大,因此不能用于循环.此外,每个涉及班次的解决方案都被排除在外,因为它太慢了.

我相信最简单的方法是使用groupbyhead方法,但是我不知道如何替换原始数据帧.

例子:

df = pd.DataFrame([['A','Z',1.11],['B','Z',2.1],['C','Z',3.1],['D', 'X', 2.1], ['E','X',4.3],['E', 'X', 2.1], ['F','X',4.3]])
Run Code Online (Sandbox Code Playgroud)

在此输入图像描述

要选择我们想要更改的元素,我们可以执行以下操作:

df.groupby(by=1).head(1)[2] = np.nan
Run Code Online (Sandbox Code Playgroud)

但是在原始数据帧中没有任何变化.
目标是获得以下内容:

在此输入图像描述

编辑:

根据评论,我们不会df[1]回到已经看过的小组,例如['Z', 'Z', 'X', 'Z']不可能.

use*_*203 5

使用maskshift

df[2] = df[2].mask(df[1].ne(df[1].shift(1)))
Run Code Online (Sandbox Code Playgroud)

使用masked_array:

df[2] = np.ma.masked_array(df[2], df[1].ne(df[1].shift(1))).filled(np.nan)
# array([nan, 2.1, 3.1, nan, 4.3, 2.1, 4.3])
Run Code Online (Sandbox Code Playgroud)

使用np.rollloc:

a = df[1].values
df.loc[np.roll(a, 1)!=a, 2] = np.nan
Run Code Online (Sandbox Code Playgroud)

   0  1    2
0  A  Z  NaN
1  B  Z  2.1
2  C  Z  3.1
3  D  X  NaN
4  E  X  4.3
5  E  X  2.1
6  F  X  4.3
Run Code Online (Sandbox Code Playgroud)


jpp*_*jpp 5

您可以使用numpy.where矢量化条件赋值.这个假设df[1]已经排序.

df[2] = np.where(df[1].duplicated(), df[2], np.nan)
Run Code Online (Sandbox Code Playgroud)

如果不能假设排序:

df[2] = np.where(df[1] != df[1].shift(), np.nan, df[2])
Run Code Online (Sandbox Code Playgroud)

结果:

   0  1    2
0  A  Z  NaN
1  B  Z  2.1
2  C  Z  3.1
3  D  X  NaN
4  E  X  4.3
5  E  X  2.1
6  F  X  4.3
Run Code Online (Sandbox Code Playgroud)

可以使用等效逻辑pd.DataFrame.mask.


WeN*_*Ben 5

运用

df[2].mask(df.groupby(1).cumcount().eq(0))
Out[41]: 
0    NaN
1    2.1
2    3.1
3    NaN
4    4.3
5    2.1
6    4.3
Name: 2, dtype: float64

#df[2] = df[2].mask(df.groupby(1).cumcount().eq(0))
Run Code Online (Sandbox Code Playgroud)