【问题标题】:Group wise matching in pandas dataframe熊猫数据框中的分组匹配
【发布时间】:2019-08-20 03:33:44
【问题描述】:

我有一个熊猫数据框,它有两列。第一列代表项目的name,第二列代表它的一些被编码为整数的属性。一个项目可以有多个属性。这是一个示例

    name                ids
0   A                   147 616 813
1   B                   51 616 13 813
2   C                   776
3   D                   51 671 13 813 1092
4   E                   13 404 492 903 1093

有 300 个这样的独特属性编码为整数,然后在 id 列中的字符串中表示。我想要达到的目标:

  1. 为每个 id 找到它出现的行。例如,为了检查 id 13,我将获取行 1, 3 and 4
  2. 在我们的数据集中,与此 ID 相关的所有唯一 ID 是什么?例如,我会说对于 id 13: [51, 616, 813, 671, 1092, 404, 492, 903, 1093]
  3. 一旦我们为每个 id 分组了行,我如何比较给定的 id 是否在该组中?例如,我想检查 id 52 是否曾经与 id 13 发生过,如果是,在哪里以及出现了多少次?

我一直在考虑这个问题,但无法找到一种有效的方法来获得前两个和一个有效的方法以及 DS 为 3)。请帮忙!

【问题讨论】:

    标签: python python-3.x pandas optimization data-analysis


    【解决方案1】:

    以下是三个功能的建议:

    import pandas as pd
    # first we create the data
    data = pd.DataFrame({'name': ['A','B','C','D','E'],
                    'ids': ['147 616 813','51 616 13 813','776','51 671 13 813 
    1092','13 404 492 903 1093']})
    
    def func1(num, series):
        # num must be an int
        # series a Pandas series
        tx = series.apply(lambda x: True if str(num) in x.split() else False)
    
        output_list = series.index[tx].tolist()
    
        return output_list
    
     def func2(num, series):
        # num must be an int
        # series a Pandas series
        series = series.iloc[func1(num, series)]
    
        series = series.apply(lambda x: x.split()).tolist()
    
        output_list = set([item for sublist in series for item in sublist])
        output_list.remove(str(num))
        return list(output_list)
    
    def func3(num1,num2,series):
        # num1 must be an int
        # num2 must be an int
        # series a Pandas series
    
        if str(num1) in func2(num2, series):
            num1_index = func1(num1, series)
            num2_index = func1(num2, series)
            return list(set(num1_index) & set(num2_index))
        else:
            return 'no match'
    

    然后你可以测试它们:

    func1(13, data['ids'])
    func2(13, data['ids'])
    func3(13,51,data['ids'])
    

    【讨论】:

      【解决方案2】:

      不使用任何for循环的解决方案

      import pandas as pd
      import numpu as np
      
      df = pd.DataFrame({'name':'A B C D E'
                         .split(),'ids':['147 616 813','51 616 13 813','776','51 671 13 813 1092','13 404 492 903 1093']})
      
      #Every input of i_d to functions in int
      #to get indexes where id occurs
      def rows(i_d):
          i_d = str(i_d)
          pattern1 = "[^0-9]" +i_d+"[^0-9]"
          pattern2 = i_d+"[^0-9]"    
          pattern3 = "[^0-9]" +i_d 
      
          mask = df.ids.apply(lambda x: True if (len(re.findall(pattern1,x)) > 0) | (len(re.findall(pattern2,x))) | (len(re.findall(pattern3,x)) > 0) else False)
      
          return df[mask].index.tolist()
      
      #to get other ids occuring with the id in discussion
      def colleagues(i_d):
          i_d = str(i_d)
      
          df.loc[rows(i_d),'temp'] = 1
          k =list(set(df.groupby('temp').ids.apply(lambda x: ' '.join(x)).iloc[0].split()))
          k.remove(i_d)
          df.drop('temp',axis=1,inplace=True)
      
          return k
      
      #to get row indexes where 2 ids occur together
      def third(i_d1,i_d2):
          i_d1 = str(i_d1)
          i_d2 = str(i_d2)
      
          common_rows = list(np.intersect1d(rows(i_d1),rows(i_d2)))
          if len(common_rows) > 0:
              return print('Occured together at rows ',common_rows)
          else:
              return print("Didn't occur together")
      

      【讨论】:

      • 感谢您的回答,但for 循环并不是一种有效的方法
      • @mlRocks 查看更新后的代码,希望对您有所帮助:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-11-03
      • 2021-08-08
      • 2019-06-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-03
      相关资源
      最近更新 更多