【问题标题】:How to get unique values of a dataframe column when there are lists - python有列表时如何获取数据框列的唯一值 - python
【发布时间】:2019-10-17 13:38:13
【问题描述】:

我有以下数据框,我想在其中打印 color 列的唯一值。

df = pd.DataFrame({'colors': ['green', 'green', 'purple', ['yellow , red'], 'orange'], 'names': ['Terry', 'Nor', 'Franck', 'Pete', 'Agnes']})

Output:
           colors   names
0           green   Terry
1           green     Nor
2          purple  Franck
3  [yellow , red]    Pete
4          orange   Agnes

如果没有[yellow , red] 行,df.colors.unique() 可以正常工作。事实上,我不断收到TypeError: unhashable type: 'list' 错误,这是可以理解的。

有没有办法在不考虑这一行的情况下仍然获得唯一值?

我尝试了以下方法,但没有成功:

df = df[~df.colors.str.contains(',', na=False)] # Nothing happens
df = df[~df.colors.str.contains('[', na=False)] # Output: error: unterminated character set at position 0
df = df[~df.colors.str.contains(']', na=False)] # Nothing happens

【问题讨论】:

  • 理想情况下这应该可以工作,df.loc[~df.colors.str.contains('[', na=False, regex=False), 'colors'].unique()
  • 以上代码返回['green', 'purple', 'orange']
  • @I.M.如果它们是唯一的或者你想忽略它们,你真的想要列表中的值吗?
  • 由于某些原因,我也得到了error: unterminated character set at position 0@MahendraSingh
  • @vb_rises 我可以忽略它们,但理想的情况是即使它们是列表格式,也要拥有列的唯一值。

标签: python pandas unique


【解决方案1】:

如果值是列表,则通过isinstance 方法检查:

#changed sample data
df = pd.DataFrame({'colors': ['green', 'green', 'purple', ['yellow' , 'red'], 'orange'], 
                   'names': ['Terry', 'Nor', 'Franck', 'Pete', 'Agnes']})

df = df[~df.colors.map(lambda x : isinstance(x, list))]
print (df)
   colors   names
0   green   Terry
1   green     Nor
2  purple  Franck
4  orange   Agnes

您的解决方案应该通过转换为字符串和regex=False 参数来更改:

df = df[~df.colors.astype(str).str.contains('[', na=False, regex=False)] 
print (df)
   colors   names
0   green   Terry
1   green     Nor
2  purple  Franck
4  orange   Agnes

另外,如果希望所有唯一值包含 pandas 0.25+ 的列表:

s = df.colors.map(lambda x : x if isinstance(x, list) else [x]).explode().unique().tolist()
print (s)
['green', 'purple', 'yellow', 'red', 'orange']

【讨论】:

    【解决方案2】:

    让我们使用type

    df.colors.apply(lambda x : type(x)!=list)
    0     True
    1     True
    2     True
    3    False
    4     True
    Name: colors, dtype: bool
    

    【讨论】:

      【解决方案3】:

      假设数据框中的每个值都很重要,这是我经常用来“解压列表”的一种技术:

      import re
      
      def unlock_list_from_string(string, delim=','):
          """
          lists are stored as strings (in csv files) ex. '[1,2,3]'
          this function unlocks that list
          """
          if type(string)!=str:
              return string
      
          # remove brackets
          clean_string = re.sub('\[|\]', '', string)
          unlocked_string = clean_string.split(delim)
          unlocked_list = [x.strip() for x in unlocked_string]
          return unlocked_list
      
      all_colors_nested = df['colors'].apply(unlock_list_from_string)
      # unnest
      all_colors = [x for y in all_colors_nested for x in y ]
      
      print(all_colors)
      # ['green', 'green', 'purple', 'yellow', 'red', 'orange']
      
      
      

      【讨论】:

      • 您的方法似乎很有趣,并且在这里效果很好,但我在我实际使用的数据框(这是一个非常大的数据框)上尝试了它,但不幸的是它失败了。不过,我会将其保留为更“正常”大小的数据框。
      • 您收到的错误是什么? (我也在大型数据帧上使用此解决方案)
      • 下一个:IOPub data rate exceeded. The notebook server will temporarily stop sending output to the client in order to avoid crashing it. To change this limit, set the config variable `--NotebookApp.iopub_data_rate_limit`.
      • 啊,您的数据框非常非常大。您可以考虑分块操作。
      【解决方案4】:

      更改输入示例

      指定的输入有一个字符串,它是一个列表(由海报指定),因此转换为字符串列表。

      # Required Import
      from ast import literal_eval
      
      df = pd.DataFrame({
          'colors': ['green', 'green', 'purple', "['yellow' , 'red']", 'orange'], 
          'names': ['Terry', 'Nor', 'Franck', 'Pete', 'Agnes']
      })
      

      执行literal_eval。欲了解更多信息,请查看literal_eval

      文字评估,以便仅在存在字符串列表的情况下将字符串转换为实际列表

      list_records = df.colors.str.contains('[', na=False, regex=False)
      df.loc[list_records, 'colors'] = df.loc[list_records, 'colors'].apply(literal_eval)
      

      独特的颜色

      适用于熊猫 >= 0.25

      df.explode('colors')['colors'].unique()
      

      给予

      ['green', 'purple', 'yellow', 'red', 'orange']
      

      【讨论】:

        猜你喜欢
        • 2020-11-27
        • 1970-01-01
        • 2021-11-16
        • 2020-07-11
        • 2022-10-13
        • 1970-01-01
        • 1970-01-01
        • 2017-10-12
        • 1970-01-01
        相关资源
        最近更新 更多