我有一个pd。具有重复索引的系列,每个索引包含一组布尔值:
FA155 False
FA155 False
FA155 False
FA155 True
FA155 True
FA155 True
FA155 True
FA155 True
FA155 False
我试图以一种有效的方式为每个不同的索引做的是仅将序列的第一个和最后一个 True 值保留为 True,并将其余值设置为 False。在 True 值之间也可以存在 False 值。
因此,对于此示例,结果将是:
FA155 False
FA155 False
FA155 False
FA155 True
FA155 False
FA155 False
FA155 False
FA155 True
FA155 False
任何帮助将不胜感激。
您可以将loc
与原始df
和反转df
一起使用idxmax
。
这将生成第一个和最后一个True
值的索引。只需将不同的索引设置为之后False
即可。
例如:
设置
z = sio("""i v
FA154 False
FA155 False
FA155 True
FA155 True
FA155 True
FA155 True
FA155 True
FA155 False
FA156 False
FA156 True
FA156 False
FA156 False
FA156 True""")
df = pd.read_table(z, delim_whitespace=True)
i v
0 FA154 False
1 FA155 False
2 FA155 True
3 FA155 True
4 FA155 True
5 FA155 True
6 FA155 True
7 FA155 False
8 FA156 False
9 FA156 True
10 FA156 False
11 FA156 False
12 FA156 True
idxmax()
这与获取df
和使用reset_index
相同。然后,获取索引列表的第一个(v1
(和最后一个(v2
(True
值:
v1 = df.groupby("i").v.idxmax().values
v2 = df[::-1].groupby("i").v.idxmax().values
并使用您的逻辑:
df.loc[v1, "v"] = True & df.loc[v1, "v"]
df.loc[v2, "v"] = True & df.loc[v2, "v"]
df.loc[~df.index.isin(np.concatenate([v1,v2])), "v"] = False
使用&
背后的想法是不要意外地将任何False
值设置为True
.
结果:
>>> df.set_index("i")
v
i
FA154 False
FA155 False
FA155 True
FA155 False
FA155 False
FA155 False
FA155 True
FA155 False
FA156 False
FA156 True
FA156 False
FA156 False
FA156 True
筛选True 值,然后聚合以查找第一个和最后一个值。然后,您可以使用 loc 替换 df 中的这些值。df
是您的数据帧。col
是具有True
值和False
值的列的名称
df["nb"] = range(df.shape[0])
df.reset_index(inplace=True)
elem = (df[df[col]==True].groupby("index")["nb"].agg({ "first_True": 'first', "last_True":"last"})).values
indexes_to_False = sum(elem.tolist(), [])
df.loc[indexes_to_False, col] = False
然后,您可以根据需要删除nb
列并重新索引
这是基于获取组起点diff
,我使用iloc
两次,因为您需要保持头部和尾部 True
df1=df.copy()
df.loc[df]=df.astype(int).diff().ne(0)[df]
df=df.iloc[::-1]
df1=df1.iloc[::-1]
df.loc[df1]+=df1.astype(int).diff().ne(0)[df1]
df=df.iloc[::-1]