Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 对数据帧中的事务链求和,由列值链接的行_Python_Pandas - Fatal编程技术网

Python 对数据帧中的事务链求和,由列值链接的行

Python 对数据帧中的事务链求和,由列值链接的行,python,pandas,Python,Pandas,我试图从一个数据帧链接多个行,以便通过连接接收方ID和发送方ID获得所有可能的路径 以下是我的数据帧示例: transaction_id sender_id receiver_id amount 0 213234 002 125 10 1 223322 017 354 90 2 343443 125 689 70 3

我试图从一个数据帧链接多个行,以便通过连接接收方ID和发送方ID获得所有可能的路径

以下是我的数据帧示例:

   transaction_id sender_id receiver_id  amount
0          213234       002         125      10
1          223322       017         354      90
2          343443       125         689      70
3          324433       689         233       5
4          328909       354         456      10
创建时使用:

df = pd.DataFrame(
    {'transaction_id': {0: '213234', 1: '223322', 2: '343443', 3: '324433', 4: '328909'},
     'sender_id': {0: '002', 1: '017', 2: '125', 3: '689', 4: '354'},
     'receiver_id': {0: '125', 1: '354', 2: '689', 3: '233', 4: '456'},
     'amount': {0: 10, 1: 90, 2: 70, 3: 5, 4: 10}}
)
我的代码的结果应该是链式ID列表和交易链的总金额。对于上面示例中的前两行,类似于:

[('002', '125', '689', '233'), 85]
[('017', '354', '456'), 100]
我已经尝试遍历这些行,并将每一行转换为
节点
类的实例,然后使用方法遍历链表,但我不知道下一步是什么:

class Node:
    def __init__(self,transaction_id,sender,receiver,amount):
        self.transac = transaction_id
        self.val = sender_id
        self.next = receiver_id
        self.amount = amount
    def traverse(self):
        node = self # start from the head node
        while node != None:
            print (node.val) # access the node value
            node = node.next # move on to the next node

for index, row in customerTransactionSqlDf3.iterrows():
    index = Node( 
        row["transaction_id"],
        row["sender_id"],
        row["receiver_id"],
        row["amount"]
    )
其他信息:

  • 发件人id值是唯一的,对于每个发件人id,只有一个可能的交易链
  • 没有循环,也不存在接收方id指向同一路径中的发送方id的链
    • 您有一个有向图,其边由
      id->id
      连接构成。您正在尝试枚举此图中的所有路径。如果不使用链表,这实际上要容易得多

      请注意,链表实现实际上并不链接节点;您的
      next
      值必须引用其他
      节点
      实例,而不是
      id

      因为路径不能有循环,所以该图被称为非循环图。您的路径也非常简单,正如您所说的,每个发送者id都不会超过一个接收方id

      在数据框中创建一个新视图,将发送者id作为索引,并将接收者id和金额列一起创建;这将使查找下一个路径元素变得非常容易。然后,您可以迭代这些列,遍历它们的路径,并对它们的数量求和,非常简单。以下代码使用已找到的路径,以避免再次遍历这些路径:

      # receiver and amount rows, indexed by sender
      edges = df[['sender_id', 'receiver_id', 'amount']].set_index('sender_id')
      paths = {}   # sender -> [sender, receiver, receiver, receiver, ...]
      totals = {}  # sender -> total amount
      
      for sender, next_, amount in edges.itertuples():
          path = paths[sender] = [sender, next_]
          totals[sender] = amount
          while True:
              if next_ in paths:
                  # re-use already found path
                  path += paths[next_]
                  totals[sender] += totals[next_]
                  break
      
              try:
                  next_, amount = edges.loc[next_]
              except KeyError:
                  break  # path complete
      
              path.append(next_)
              totals[sender] += amount
      
      通过更新遇到的每个子路径,代码仍然可以变得更有效,因此,当您为发送者id
      125
      处理第三行时,您已经处理了该路径,因为您必须为第一行从
      002
      开始的路径遍历该路径:

      for sender, next_, amount in edges.itertuples():
          if sender in paths:
              # already handled as part of a longer path
              continue
      
          paths[sender], totals[sender] = [sender, next_], amount
          senders = [sender]  # all sender ids along the path
      
          while True:
              if next_ in paths:
                  # re-use already found path
                  for sender in senders:
                      paths[sender] += paths[next_]
                      totals[sender] += totals[next_]
                  break
      
              if next_ not in edges.index:
                  break  # path complete
      
              # start a new path from this sender id
              paths[next_], totals[next_] = [next_], 0
              senders.append(next_)
      
              next_, amount = edges.loc[next_]
              for sender in senders:
                  paths[sender].append(next_)
                  totals[sender] += amount
      
      无论哪种方式,您现在都已计算出所有事务的完整路径和总数。您可以将这些列转换回其他列:

      df['path'], df['total'] = df.sender_id.map(paths), df.sender_id.map(totals)
      
      对于您的输入数据帧,它将生成:

      交易\u id发送方\u id接收方\u id金额路径合计
      0          213234       002         125      10  [002, 125, 689, 233]     85
      1          223322       017         354      90       [017, 354, 456]    100
      2          343443       125         689      70       [125, 689, 233]     75
      3          324433       689         233       5            [689, 233]      5
      4          328909       354         456      10            [354, 456]     10
      
      或者,您可以通过在任一字典上循环,将路径与总计配对:

      for id, path in paths.items():
          print(id, path, totals[id])
      
      对于您的具体示例,这同样会产生:

      002['002',125',689',233']85
      125 ['125', '689', '233'] 75
      689 ['689', '233'] 5
      017 ['017', '354', '456'] 100
      354 ['354', '456'] 10
      
      我不知道下一步是什么

      通过使用当前实现,可以通过迭代每个节点来连接两个
      节点
      对象。您还可以在
      节点
      类中添加
      已访问
      属性,以便在遍历树时识别唯一的链,即没有一条链是另一条链的子链。但是,如果您想知道每个
      发送者\u id
      的链,这可能不是必需的

      编辑:我注意到您提到的预期结果示例是前两行。这意味着每个
      sender\u id
      都应该有自己的链。修改
      遍历
      方法,以便在节点全部连接后使用

      编辑:重新实现已访问的
      属性以获取唯一链

      df=pd.DataFrame(
      {'transaction_id':{0:'213234',1:'223322',2:'34343443',3:'324433',4:'328909'},
      “发件人id:{0:'002',1:'017',2:'125',3:'689',4:'354'},
      '接收者id':{0:'125',1:'354',2:'689',3:'233',4:'456'},
      ‘金额’:{0:10,1:90,2:70,3:5,4:10}
      )
      类节点:
      定义初始(自身、交易id、发送方id、接收方id、金额):
      self.transac=事务\u id
      self.sender=sender\u id
      self.receiver=receiver\u id
      self.next=无
      self.amount=金额
      自我访问=错误
      def遍历(自身,链=无,总计=0):
      if(自访问):#撤消访问的节点
      返回
      自我访问=真实
      如果链为无:#这是遍历的开始
      链=[self.sender]
      链+=[自我接收器]
      合计+=自付金额
      如果self.next不是None:
      返回self.next.travel(链,总计)
      返回链,总计
      transc=[节点(
      行[“事务处理id”],
      行[“发送方id”],
      行[“接收方id”],
      行[“金额”]
      )对于i,df.iterrows()中的行
      #连接节点
      对于枚举(transc)中的i、v:
      对于枚举(transc)中的j,k:
      #如果接收器v与来自j的发送器相同
      如果v.receiver==k.sender:
      v、 next=k
      summary=[i.TRAVENSE()表示transc中的i]
      summary=[如果i不是None,则i代表summary中的i]#删除None
      打印(摘要)
      
      输出:

      [
      (['002', '125', '689', '233'], 85), 
      (['017', '354', '456'], 100)
      ]
      
      我认为它可以完成这项工作,但预期的结果应该是:
      [(['002',125',689',233',85),(['017',354',456',100),]
      我不需要所有的事务链id,我只需要所有可能的链将我的解决方案用于获得唯一的链。这将是非常有帮助的,如果这被标记为答案,如果这解决了你的问题。太好了!这解决了我的问题