在 python pandas 中设置切片中第一项的值

Set value of first item in slice in python pandas

所以我想制作一个数据帧的切片,然后在不复制数据帧的情况下设置该切片中第一项的值。例如:

df = pandas.DataFrame(numpy.random.rand(3,1))
df[df[0]>0][0] = 0

这里的切片是无关紧要的,只是为了示例,将再次 return 整个数据帧。重点是,通过像示例中那样进行操作,您将获得带有复制警告的设置(可以理解)。我也试过先切片,然后使用 ILOC/IX/LOC 并使用 ILOC 两次,例如:

df.iloc[df[0]>0,:][0] = 0
df[df[0]>0,:].iloc[0] = 0

而且这些都不起作用。再次-我不想复制数据帧,即使它只是切片版本。

编辑: 似乎有两种方法,使用掩码或 IdxMax。如果您的索引是唯一的,则 IdxMax 方法似乎有效,如果不是,则使用掩码方法。就我而言,索引不是唯一的,我忘记在初始 post.

中提及

我想你可以使用 idxmax for get index of first True value and then set by loc:

np.random.seed(1)
df = pd.DataFrame(np.random.randint(4, size=(5,1)))
print (df)
   0
0  1
1  3
2  0
3  0
4  3

print ((df[0] == 0).idxmax())
2

df.loc[(df[0] == 0).idxmax(), 0] = 100
print (df)
     0
0    1
1    3
2  100
3    0
4    3

df.loc[(df[0] == 3).idxmax(), 0] = 200
print (df)
     0
0    1
1  200
2    0
3    0
4    3

编辑:

没有唯一索引的解决方案:

np.random.seed(1)
df = pd.DataFrame(np.random.randint(4, size=(5,1)), index=[1,2,2,3,4])
print (df)
   0
1  1
2  3
2  0
3  0
4  3

df = df.reset_index()
df.loc[(df[0] == 3).idxmax(), 0] = 200
df = df.set_index('index')
df.index.name = None
print (df)
     0
1    1
2  200
2    0
3    0
4    3

编辑 1:

MultiIndex 的解决方案:

np.random.seed(1)
df = pd.DataFrame(np.random.randint(4, size=(5,1)), index=[1,2,2,3,4])
print (df)
   0
1  1
2  3
2  0
3  0
4  3

df.index = [np.arange(len(df.index)), df.index]
print (df)
     0
0 1  1
1 2  3
2 2  0
3 3  0
4 4  3

df.loc[(df[0] == 3).idxmax(), 0] = 200
df = df.reset_index(level=0, drop=True)

print (df)
     0
1    1
2  200
2    0
3    0
4    3

编辑 2:

cumsum的解决方案:

np.random.seed(1)
df = pd.DataFrame([4,0,4,7,4], index=[1,2,2,3,4])
print (df)
   0
1  4
2  0
2  4
3  7
4  4

mask = (df[0] == 0).cumsum().cumsum()
print (mask)
1    0
2    1
2    2
3    3
4    4
Name: 0, dtype: int32

df.loc[mask == 1, 0] = 200
print (df)
     0
1    4
2  200
2    4
3    7
4    4

考虑数据框df

df = pd.DataFrame(dict(A=[1, 2, 3, 4, 5]))

print(df)

   A
0  1
1  2
2  3
3  4
4  5

创建一些任意切片 slc

slc = df[df.A > 2]

print(slc)

   A
2  3
3  4
4  5

使用index[0]loc

访问dfslc的第一行
df.loc[slc.index[0]] = 0
print(df)

   A
0  1
1  2
2  0
3  4
4  5
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.rand(6,1),index=[1,2,2,3,3,3])
df[1] = 0
df.columns=['a','b']
df['b'][df['a']>=0.5]=1
df=df.sort(['b','a'],ascending=[0,1])
df.loc[df[df['b']==0].index.tolist()[0],'a']=0

在此方法中,不会创建数据帧的额外副本,但引入了一个额外的列,可以在处理后删除。要选择任何索引而不是第一个索引,您可以按如下方式更改最后一行

df.loc[df[df['b']==0].index.tolist()[n],'a']=0

更改切片中的第 n 个项目

df

          a  
1  0.111089  
2  0.255633  
2  0.332682  
3  0.434527  
3  0.730548  
3  0.844724  

切片和标记后的 df

          a  b
1  0.111089  0
2  0.255633  0
2  0.332682  0
3  0.434527  0
3  0.730548  1
3  0.844724  1

将切片中第一项(标记为 0)的值更改为 0 后

          a  b
3  0.730548  1
3  0.844724  1
1  0.000000  0
2  0.255633  0
2  0.332682  0
3  0.434527  0

因此,使用一些答案,我设法找到了一种单一的方式来做到这一点:

np.random.seed(1)
df = pd.DataFrame(np.random.randint(4, size=(5,1)))
print df
   0
0  1
1  3
2  0
3  0
4  3
df.loc[(df[0] == 0).cumsum()==1,0] = 1
   0
0  1
1  3
2  1
3  0
4  3

本质上这是使用带有 cumsum 的掩码。