Groupby搜索第一个和最后一个True值

时间:2018-05-28 18:02:34

标签: python pandas

我有一个带有重复索引的pd.Series,每个索引都包含一组布尔值:

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

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:3)

您可以将locidxmax一起使用原始df和倒置df

这将产生您的第一个和最后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)和最后(v2True值:

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

答案 1 :(得分:1)

You filter True values and then you aggregate to find the first and last values. Then you can use loc to replace those values in df. df is your dataframe. col is the name of your column with True and False values

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

Then you can drop the column nb and reindex if you wish

答案 2 :(得分:1)

This is based on the diff to get the group starting point , I am using iloc twice since you need keep the head and tail 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]