递归CTE /熊猫的传递闭包

时间:2020-06-29 07:12:40

标签: python pandas transitive-closure

enter image description here

我的情况:

  • 用户A为(欺诈者)。
  • 用户B不是(欺诈者)。但是,系统将不允许用户B 做任何动作。因为B和A使用的是同一个电话 号码(与欺诈用户共享的属性)。 (1层)。
  • 用户D不是(欺诈者)。但是D与B使用相同的Deviceid B与欺诈用户共享属性。然后将用户D阻止为 好。在这种情况下,有2层。 D与B比较,B与 与A。

我可以使用递归CTE做到这一点。但是,我的主管要求我为此找到另一种方法:(。

递归CTE代码:

public Form1()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }

输出:

enter image description here

我可以使用Python做到这一点吗?我在考虑熊猫

with recursive cte as (
      select ID, Email, MobileNo, DeviceId, IPAddress, id as tracking
      from tableuser
      where isfraudsterstatus = 1
      union all
      select u.id, u.email, u.mobileno, u.deviceid, u.ipaddress , concat_ws(',', cte.tracking, u.id)
      from cte join
           tableuser u
           on u.email = cte.email or
              u.mobileno = cte.mobileno or
              u.deviceid = cte.deviceid or 
              u.ipaddress = cte.ipaddress
      where find_in_set(u.id, cte.tracking) = 0
     )
select *
from cte;

1 个答案:

答案 0 :(得分:1)

这是一个解决方案。它基本上计算了欺诈者用户的可传递关闭:

df = pd.DataFrame({'userId':
                       [1, 2, 3, 4,],
                   'phone':
                       ['01111', '01111', '53266', '7455'],
                   'email':
                       ['aziz@gmail', 'aziz1@gmail', 'aziz1@gmail', 'aziz2@gmail'],
                   'deviceId':
                       ['Ab123', 'Ab1234', 'Ab12345', 'Ab12345'],
                   'isFraud':
                   [1,0,0,0]})


def expand_fraud(no_fraud, fraud, col_name):
    t = pd.merge(no_fraud, fraud, on = col_name)
    if len(t):
        print(f"Found Match on {col_name}")
        df.loc[df.userId.isin(t.userId_x), "isFraud"] = 1
        return True
    return False

while True:
    added_fraud = False
    fraud = df[df.isFraud == 1]
    no_fraud = df[df.isFraud == 0]
    added_fraud |= expand_fraud(no_fraud, fraud, "deviceId")
    added_fraud |= expand_fraud(no_fraud, fraud, "email")
    added_fraud |= expand_fraud(no_fraud, fraud, "phone")   
    if not added_fraud:
        break

print(df)

输出为:

   userId  phone        email deviceId  isFraud
0       1  01111   aziz@gmail    Ab123        1
1       2  01111  aziz1@gmail   Ab1234        1
2       3  53266  aziz1@gmail  Ab12345        1
3       4   7455  aziz2@gmail  Ab12345        1