在 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
访问df
中slc
的第一行
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 的掩码。
所以我想制作一个数据帧的切片,然后在不复制数据帧的情况下设置该切片中第一项的值。例如:
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
df
中slc
的第一行
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 的掩码。