设置python中切片中第一项的值
因此,我想创建一个数据帧片段,然后设置该片段中第一个项目的值,而不复制数据帧。例如:设置python中切片中第一项的值,python,pandas,slice,mask,argmax,Python,Pandas,Slice,Mask,Argmax,因此,我想创建一个数据帧片段,然后设置该片段中第一个项目的值,而不复制数据帧。例如: df = pandas.DataFrame(numpy.random.rand(3,1)) df[df[0]>0][0] = 0 这里的切片是不相关的,仅用于示例,它将再次返回整个数据帧。重点是,通过像示例中那样操作,您可以获得一个带有复制警告的设置(可以理解)。我还尝试过先进行切片,然后使用ILOC/IX/LOC,再使用ILOC两次,例如: df.iloc[df[0]>0,:][0] = 0 d
df = pandas.DataFrame(numpy.random.rand(3,1))
df[df[0]>0][0] = 0
这里的切片是不相关的,仅用于示例,它将再次返回整个数据帧。重点是,通过像示例中那样操作,您可以获得一个带有复制警告的设置(可以理解)。我还尝试过先进行切片,然后使用ILOC/IX/LOC,再使用ILOC两次,例如:
df.iloc[df[0]>0,:][0] = 0
df[df[0]>0,:].iloc[0] = 0
这两种方法都不管用。再一次-我不想复制数据帧,即使它只是切片版本
编辑:
似乎有两种方法,使用掩码或IdxMax。如果索引是唯一的,则IdxMax方法似乎有效,如果不是唯一的,则掩码方法有效。在我的例子中,索引不是唯一的,我在最初的文章中忘记提到了这一点。我认为您可以使用get index of firstTrue
值,然后通过以下方式设置:
编辑: 非唯一索引的解决方案:
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:
使用多索引的解决方案
:
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:
解决方案具有双重功能:
考虑数据帧
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
使用
索引[0]
和loc
df.loc[slc.index[0]] = 0
print(df)
A
0 1
1 2
2 0
3 4
4 5
在此方法中,不会创建数据帧的额外副本,但会引入一个额外列,该列可以在处理后删除。要选择任何索引而不是第一个索引,可以按如下方式更改最后一行
df.loc[df[df['b']==0].index.tolist()[n],'a']=0
更改切片中任何第n项的步骤
df
切片和贴标签后的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后
因此,使用一些答案,我设法找到了一种简单的方法:
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
本质上,这是使用与累积数内联的掩码。如果第二个7不直接位于第一个7之后,也就是说,如果布尔数组上的
cumsum
的结果将有几个1
s?@juanpa.arrivillaga-谢谢,你是对的。给我一秒钟,我认为最可靠的方法,而且只有在索引唯一的情况下才可靠,就是从切片中获取索引,然后从索引中获取第一个值,并在原始帧上使用该值进行设置。啊,idxmax
,非常非常聪明@RexFuzzle-是的,如果不是连续值,它也可以工作,请参阅第二个不同条件的解决方案。我希望不要复制df的任何部分,因为它很大,甚至切片可能相当大。@RexFuzzle您说切片是任意的,我假设已经存在。从该片中,我获取第一个索引值并使用它修改原始的df
。我认为类似df.loc[slice,另一个\u片]
的内容应该比df.loc[slice].loc[:,另一个\u片]
更少占用内存。这可以同时对行和列进行切片,但在不同的条件下似乎不可能按行进行切片。实际上我不确定,也许我心里想的没有道理。
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
a
1 0.111089
2 0.255633
2 0.332682
3 0.434527
3 0.730548
3 0.844724
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
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