问题描述
我不知道如何解释,所以我会尽力而为。
我合并了两个数据集以获得以下数据:
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 以一行结束。但需要考虑以下几点:
-在 code1
、code2
或 code3
中,当 code1、code2 或 code3 为 "BBB" 或 "CCC" 时,或者如果 {{1} } 大于或等于 3 。
之后很容易创建一个名为 payment
的变量,它是 length
和 datestamp
之间的天数差异,但我需要让每个变量只有 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()
:
-
print(soup.find(class_="_1mil").find_all("div")[-1].text)
检查mask1
或BBB
isin()
any()
是否为CCC
-like 列 -
code
检查是否mask2
然后 payment >= 3
会给你第一场比赛:
(mask1 | mask2).idxmax()