将第一个非零列值标记为1,其余0标记为多个列

2024-06-30 16:34:16 发布

您现在位置:Python中文网/ 问答频道 /正文

请协助完成以下工作

import pandas as pd
df = pd.DataFrame({'Grp': [1,1,1,1,2,2,2,2,3,3,3,4,4,4], 'Org1': ['x','x','y','y','z','y','z','z','x','y','y','z','x','x'], 'Org2': ['a','a','b','b','c','b','c','c','a','b','b','c','a','a'], 'Value': [0,0,3,1,0,1,0,5,0,0,0,1,1,1]})
df

***我需要第一个非零值,其“FLAG”=1,其他值为0

详情:

对于每个唯一的“Grp、Org1、Org2”集合,并基于“值”“标志”将1和其他值设为0

如果列中的值均为0,则所有值的标志均为0

如果列中的值都不为零,则第一个实例的标志为1,其他值为0

我期待的输出如下

+----+-----+------+------+-------+------+
|    | Grp | Org1 | Org2 | Value | FLAG |
+----+-----+------+------+-------+------+
|  0 |   1 | x    | a    |     0 |    0 |
|  1 |   1 | x    | a    |     0 |    0 |
|  2 |   1 | y    | b    |     3 |    1 |
|  3 |   1 | y    | b    |     1 |    0 |
|  4 |   2 | z    | c    |     0 |    0 |
|  5 |   2 | y    | b    |     1 |    1 |
|  6 |   2 | z    | c    |     0 |    0 |
|  7 |   2 | z    | c    |     5 |    1 |
|  8 |   3 | x    | a    |     0 |    0 |
|  9 |   3 | y    | b    |     0 |    0 |
| 10 |   3 | y    | b    |     0 |    0 |
| 11 |   4 | z    | c    |     1 |    1 |
| 12 |   4 | x    | a    |     1 |    1 |
| 13 |   4 | x    | a    |     1 |    0 |
+----+-----+------+------+-------+------+

Tags: 实例importdataframepandasdfvalue标志as
2条回答

从一个简单的标志开始,确定是否设置了该值

df = df.assign(FLAG=df.Value.where(df.Value == 0, 1))
df
#     Grp Org1 Org2  Value  FLAG
# 0     1    x    a      0     0
# 1     1    x    a      0     0
# 2     1    y    b      3     1
# 3     1    y    b      1     1
# 4     2    z    c      0     0
# 5     2    y    b      1     1
# 6     2    z    c      0     0
# 7     2    z    c      5     1
# 8     3    x    a      0     0
# 9     3    y    b      0     0
# 10    3    y    b      0     0
# 11    4    z    c      1     1
# 12    4    x    a      1     1
# 13    4    x    a      1     1

然后,使用groupby在每个组中独立工作,您可以找到通过使用pd.Series.cummax后跟pd.Series.diff设置的第一个标志

flag = df.groupby(['Grp', 'Org1', 'Org2'])['FLAG'].transform(lambda x: x.cummax().diff())                                                                                                                                                    
df['FLAG'] = flag.where(flag.notnull(), df['FLAG']).astype(int)
df
#     Grp Org1 Org2  Value  FLAG
# 0     1    x    a      0     0
# 1     1    x    a      0     0
# 2     1    y    b      3     1
# 3     1    y    b      1     0
# 4     2    z    c      0     0
# 5     2    y    b      1     1
# 6     2    z    c      0     0
# 7     2    z    c      5     1
# 8     3    x    a      0     0
# 9     3    y    b      0     0
# 10    3    y    b      0     0
# 11    4    z    c      1     1
# 12    4    x    a      1     1
# 13    4    x    a      1     0

使用cummax将把第一个1条目之后的所有内容也转换为1,这样diff将是所有的0,除了从01的第一步

我们可以在这里使用GroupBy.idxmax

m = df['Value'].ne(0)
idx = df['Value'].where(m).groupby([df['Grp'], df['Org1']]).idxmax()
df['FLAG'] = df.index.isin(idx).astype(int)

    Grp Org1 Org2  Value  FLAG
0     1    x    a      0     0
1     1    x    a      0     0
2     1    y    b      3     1
3     1    y    b      1     0
4     2    z    c      0     0
5     2    y    b      1     1
6     2    z    c      0     0
7     2    z    c      5     1
8     3    x    a      0     0
9     3    y    b      0     0
10    3    y    b      0     0
11    4    z    c      1     1
12    4    x    a      1     1
13    4    x    a      1     0

相关问题 更多 >