微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

根据特定条件,将第一次出现在一个列中

如何解决根据特定条件,将第一次出现在一个列中

我不知道如何解释,所以我会尽力而为。

我合并了两个数据集以获得以下数据:

ID | active_date | datestamp  | code1 | code2 | code3 | payment
01 | 01/01/2020  | 10/06/2020 | AAA   | .     | .     | 1
01 | 01/01/2020  | 11/06/2020 | AAA   | .     | .     | 1
01 | 01/01/2020  | 12/06/2020 | BBB   | AAA   | .     | 2
01 | 01/01/2020  | 13/06/2020 | BBB   | AAA   | .     | 2
02 | 10/01/2020  | .          | .     | .     | .     | .
03 | 18/01/2020  | 15/05/2020 | CCC   | BBB   | AAA   | 4
03 | 18/01/2020  | 16/05/2020 | CCC   | BBB   | AAA   | 4
04 | 20/01/2020  | 24/04/2020 | AAA   | .     | .     | 2
04 | 20/01/2020  | 25/04/2020 | AAA   | .     | .     | 3
04 | 20/01/2020  | 26/04/2020 | AAA   | .     | .     | 3
05 | 24/01/2020  | 06/05/2020 | DDD   | .     | .     | 1
05 | 24/01/2020  | 07/05/2020 | DDD   | .     | .     | 1 

我需要做的基本上是每个 ID 以一行结束。但需要考虑以下几点:

-在 code1code2code3 中,当 code1、code2 或 code3 为 "BBB" 或 "CCC" 时,或者如果 {{1} } 大于或等于 3 。

之后很容易创建一个名为 payment 的变量,它是 lengthdatestamp间的天数差异,但我需要让每个变量只有 1 行具有这些特征的 ID。

最终输出应如下所示:

active_date

-保留 ID | active_date | datestamp | code1 | code2 | code3 | payment 01 | 01/01/2020 | 12/06/2020 | BBB | AAA | . | 2 02 | 10/01/2020 | . | . | . | . | . 03 | 18/01/2020 | 15/05/2020 | CCC | BBB | AAA | 4 04 | 20/01/2020 | 25/04/2020 | AAA | . | . | 3 05 | 24/01/2020 | 06/05/2020 | DDD | . | . | 1 的第三行,因为代码 1 中有 BBB。

-必须保留 01,即使它没有填充任何东西

-保留 02 因为它是该 ID 在 code1 和 code2 中带有 BBB 和 CCC 的第一行

-保留03的第二行,因为它的付款为3,所以我保留了第一行。

-保留04的第一行,因为它不满足条件,但它可以是05的任何一行

我希望这是有道理的。总之,我想按/删除重复项进行分组,但如果该 ID 在某一时刻满足条件,我离开的行必须是第一次出现。

尝试过 groupby,但我无法在不同行中处理这么多条件。

解决方法

粗糙的一个。独立计算多个选项并组合。代码如下

#meets greater than equal to 3 rule
df['m']=df['payment'].str.extract('(\d+)').astype(float).ge(3)#create temp ro
a=df[df['m']]

#meets BBB,CCC rule

b=df[df['code1'].isin(["BBB","CCC"])|df['code2'].isin(["BBB","CCC"])|df['code3'].isin(["BBB","CCC"])].drop_duplicates(subset=['code1','code1','code1'],keep='first')

#meets unique row rule

c=df.drop_duplicates(subset=['ID'],keep='first')

#combine a,b,c and drop duplicates
df1=pd.concat([a,c],axis=0).drop_duplicates(subset=['code1',keep='first').drop('m',1)

print(df1)

     ID active_date   datestamp code1 code2 code3 payment
5    3  18/01/2020  15/05/2020   CCC   BBB   AAA       4
8    4  20/01/2020  25/04/2020   AAA     .     .       3
2    1  01/01/2020  12/06/2020   BBB   AAA     .       2
4    2  10/01/2020           .     .     .     .       .
10   5  24/01/2020  06/05/2020   DDD     .     .       1
,

使用:

为方便起见,我们将 . 替换为 nan 并将付款数据类型从 object 转换为 float

df.replace(to_replace='.',value = np.nan,inplace = True)
df.payment = df.payment.astype(np.float)

现在根据指定的条件分配存储 True/False 的列。

cond = (df[['code1','code2','code3']].isin(['BBB','CCC']).any(axis = 1)
        | (df.payment >= 3))
df['cond'] = cond

这会检查前两个条件。现在让我们将所有 True 值分配给不满足任何条件的 id(因此我们选择任何随机行)。

df['cond'] = cond | df.groupby('ID')['cond'].transform(lambda x: ~np.any(x))

现在为每个 ID 选择包含 True 值的第一行。

df = (df[df['cond']].drop_duplicates(keep = 'first',subset = ['ID','cond'])
      .drop(columns = ['cond']).replace(np.nan,'.'))

输出:

>>> df
    ID active_date   datestamp code1 code2 code3 payment
2    1  01/01/2020  12/06/2020   BBB   AAA     .       2
4    2  10/01/2020           .     .     .     .       .
5    3  18/01/2020  15/05/2020   CCC   BBB   AAA       4
8    4  20/01/2020  25/04/2020   AAA     .     .       3
10   5  24/01/2020  06/05/2020   DDD     .     .       1

您可以用 '.' 替换 NaN 值。

,

如果我理解正确的话,你可以取两个条件中的idxmax()

  1. print(soup.find(class_="_1mil").find_all("div")[-1].text) 检查 mask1BBB isin() any() 是否为 CCC-like 列
  2. code 检查是否 mask2

然后 payment >= 3 会给你第一场比赛:

(mask1 | mask2).idxmax()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。