【问题标题】:Iterating through a column of lists and appending other columns based on list order遍历列表列并根据列表顺序附加其他列
【发布时间】:2021-03-02 17:26:22
【问题描述】:
cats = {'lesson_name': {0: 'Mutt',
  1: 'Ragdoll',
  2: 'Black',
  3: 'Calico',
  4: 'Tortoise',
  5: 'Mainecoon'},
 'tag_list': {0: ['Orange', 'Black', 'White'],
  1: ['Grey', 'White'],
  2: ['Black','Brown'],
  3: ['Orange','Grey','White'],
  4: ['Orange', 'Brown','White'],
  5: ['Grey','White']},
 'Orange': {0: '',
  1: '',
  2: '',
  3: '',
  4: '',
  5: ''},
 'Black': {0: '',
  1: '',
  2: '',
  3: '',
  4: '',
  5: ''},
 'White': {0: '',
  1: '',
  2: '',
  3: '',
  4: '',
  5: ''},
 'Grey': {0: '',
  1: '',
  2: '',
  3: '',
  4: '',
  5: ''},
 'Brown': {0: '',
  1: '',
  2: '',
  3: '',
  4: '',
  5: ''}}

cats_frame = pd.DataFrame(cats)

我正在尝试根据“tag_list”列中列表的顺序创建一个函数来附加颜色列(橙色、黑色、白色、灰色、棕色)。例如,如果“橙色”是 tag_list 中的第一种颜色,我希望该行在橙色列中有一个“1”,如果列表中的第二种颜色是“黑色”,我希望该行有一个“ 2' 在黑色列中。

我正在考虑为每种颜色制作一个函数并尝试过:

def black(df):
        
    for (df['tag_list'],j) in df.iteritems():
        
        if [j][0] == 'Black':
            return 1
        
        if [j][1] == 'Black':
            return 2
        
        if [j][2] == 'Black':
            return 3

        else:
            return 0
        
cats_frame['Black'] = cats_frame.apply(black,1)

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    这是解决问题的一种方法:

    tag = pd.DataFrame(cats_frame['tag_list'].tolist())
    tag_order = tag.stack().reset_index(level=1)\
                   .set_index(0, append=True)['level_1'].add(1).unstack(fill_value=0)
    
    cats_frame.update(tag_order)
    

    详情:

    >>> tag
    
            0      1      2
    0  Orange  Black  White
    1    Grey  White   None
    2   Black  Brown   None
    3  Orange   Grey  White
    4  Orange  Brown  White
    5    Grey  White   None
    
    >> tag_order
    
    0  Black  Brown  Grey  Orange  White
    0      2      0     0       1      3
    1      0      0     1       0      2
    2      1      2     0       0      0
    3      0      0     2       1      3
    4      0      2     0       1      3
    5      0      0     1       0      2
    
    >> cats_frame
    
      lesson_name                tag_list Orange Black White Grey Brown
    0        Mutt  [Orange, Black, White]      1     2     3    0     0
    1     Ragdoll           [Grey, White]      0     0     2    1     0
    2       Black          [Black, Brown]      0     1     0    0     2
    3      Calico   [Orange, Grey, White]      1     0     3    2     0
    4    Tortoise  [Orange, Brown, White]      1     0     3    0     2
    5   Mainecoon           [Grey, White]      0     0     2    1     0
    

    【讨论】:

    • 链接这些操作真是太棒了!但这似乎比其他基于 for 的答案要慢,您认为为什么? (快速基准测试为其他人提供了 777 和 1250 微秒,为此提供了 4630 微秒)
    • 感谢@MustafaAydın :) 恕我直言,在处理较大的数据集时,对于较小的数据集,使用 for 循环应该会更有效。尝试增加数据框的大小,然后检查性能,如果发现任何差异,请告诉我。
    • @MustafaAydın 您可以尝试使用cats_frame = pd.concat([cats_frame]*10000, ignore_index=True) 重新创建一个更大的数据框,然后您可以使用timeit 来检查性能。
    • 确实,119 ms vs 8.42 s 和 12.2 s!谢谢
    【解决方案2】:

    我会警告这一点,可能有更有效的方法可以做到这一点,但除非您的数据框很大,否则这是使用df.iterrows() 完成它的合理方法

    #iterate over the rows
    for idx, cols in cats_frame.iterrows():
        #iterate over the columns containing color names
        for c in cats_frame.columns[2:]:
            #Check whether the column name appears in the list
            if c in cols['tag_list']:
                #If it does, find the index in the list, add 1 due to zero-indexing, and assign the value
                cols[c]=cols['tag_list'].index(c)+1
            else:
                #otherwise, add 0
                cols[c]=0
    
        lesson_name tag_list                Orange  Black   White   Grey    Brown
    0   Mutt        [Orange, Black, White]  1       2       3       0       0
    1   Ragdoll     [Grey, White]           0       0       2       1       0
    2   Black       [Black, Brown]          0       1       0       0       2
    3   Calico      [Orange, Grey, White]   1       0       3       2       0
    4   Tortoise    [Orange, Brown, White]  1       0       3       0       2
    5   Mainecoon   [Grey, White]           0       0       2       1       0
    

    【讨论】:

      【解决方案3】:
      # i holds index e.g. 1; a_list is for example [Grey, White] in the second turn
      for i, a_list in enumerate(cats_frame.tag_list):
          # j becomes the index number (starting at 1), color becomes e.g. "Grey"
          for j, color in enumerate(a_list, start=1):
              # put numbers according to tag list to the position
              # where i points to the row and color points to the column
              cats_frame.loc[i, color] = str(j)
      

      然后

        lesson_name                tag_list Orange Black White Grey Brown
      0        Mutt  [Orange, Black, White]      1     2     3
      1     Ragdoll           [Grey, White]                  2    1
      2       Black          [Black, Brown]            1                2
      3      Calico   [Orange, Grey, White]      1           3    2
      4    Tortoise  [Orange, Brown, White]      1           3          2
      5   Mainecoon           [Grey, White]                  2    1
      

      【讨论】:

        猜你喜欢
        • 2020-11-08
        • 2018-10-28
        • 2014-07-16
        • 2019-12-29
        • 2012-08-15
        • 2019-08-02
        • 2022-01-03
        • 2012-10-05
        • 1970-01-01
        相关资源
        最近更新 更多