【问题标题】:Python Pandas Dataframe: add new column based on existing column, which contains lists of listsPython Pandas Dataframe:基于现有列添加新列,其中包含列表列表
【发布时间】:2021-03-08 19:11:49
【问题描述】:

我正在尝试在下面的数据框中添加一列,这将告诉我一个人是否属于绿色类别。 对于那个人,它只会显示 Y 或 N,具体取决于列类别是否包含它。 问题是列类别在某些行中仅包含一个字符串,而在其他行中包含字符串列表,甚至在其他行中包含列表列表。


import pandas as pd

df = pd.DataFrame({'user': ['Bob', 'Jane','Theresa', 'Alice'], 
                   'category': [[['green'],['red']],'blue',['green'],[['yellow','purple'],'green','brown']]})

如何才能查看每一行的列是否包含特定的“绿色”字符串?

谢谢。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    我不会费心整理列表,只需使用基本的字符串匹配:

    df['category'].astype(str).str.contains(r'\bgreen\b')
    
    0     True
    1    False
    2     True
    3     True
    Name: category, dtype: bool
    

    添加单词边界检查\b,这样我们就不会意外匹配诸如“greenery”或“greenwich”之类的单词,它们将“green”作为较大单词的一部分。


    df.assign(has_green=df['category'].astype(str)
                                      .str.contains(r'\bgreen\b')
                                      .map({True: 'Y', False: 'N'}))
    
          user                          category has_green
    0      Bob                  [[green], [red]]         Y
    1     Jane                              blue         N
    2  Theresa                           [green]         Y
    3    Alice  [[yellow, purple], green, brown]         Y
    

    【讨论】:

    • 很好的答案。但是关于str accessor 的问题。我大致知道str的作用是什么。但是,在这种情况下,我会感到困惑。例如,在第一行,有一个列表列表,我猜str 访问第一个列表中的值,但green 嵌套在另一个列表中。那么,我们不应该添加另一个str 来访问嵌套列表吗?如果您能推荐一个完全掌握该系列中str 的想法的来源,我将不胜感激。或者也许你可以在这里解释发生了什么。谢谢!
    • @ashkangh 我将列表转换为字符串,因此字符串中的内容不再重要 - 它只是字母。
    【解决方案2】:

    您需要使用recursive flatten

    import pandas as pd
    df = pd.DataFrame({'user': ['Bob', 'Jane','Theresa', 'Alice'], 'category': [[['green'],['red']],'blue',['green'],[['yellow','purple'],'green','brown']]})
    
    def flatten(x):
        rt = []
        for i in x:
            if isinstance(i,list): rt.extend(flatten(i))
            else: rt.append(i)
        return rt
    
    def is_green(x):
        flat_list = flatten(x)
        if "green" in flat_list:
            return True
        else:
            return False
    
    df["has_green"] = df["category"].apply(lambda x: is_green(x))
    
    print(df)
    
          user                          category  has_green
    0      Bob                  [[green], [red]]       True
    1     Jane                              blue      False
    2  Theresa                           [green]       True
    3    Alice  [[yellow, purple], green, brown]       True
    

    【讨论】:

    • 我现在正在尝试解决方案,唯一的问题是我之前没有添加它,有些行没有。你会在哪里引入 else 条件或者你会做什么,例如,如果 Jane 的类别是 None?谢谢!
    • 在 is_green() 部分@Rodrigo,您可以添加检查是否为非;如果 x 为无:...,请告诉我这是否有帮助,如果有帮助,请接受答案?
    • 谢谢!我怎样才能接受两个正确的答案?
    • 不能,只能选择一个。
    【解决方案3】:

    虽然我同意基本字符串匹配可以解决问题,但我想提请注意,使用pd.core.common.flatten 可以很容易地实现扁平化列表:

    import pandas as pd
    import ast
    
    df = pd.DataFrame({'user': ['Bob', 'Jane','Theresa', 'Alice', 'John'], 
                       'category': [[['green'],['red']],'blue',['green'],[['yellow','purple'],'green','brown'], None]})
    
    def fix_list(text):
        try:
            if '[' in text:
                text = ast.literal_eval(text)
            else: 
                text = [text]
        except:
            text = []
        return list(pd.core.common.flatten(text))
        
    df['category'] = df['category'].apply(fix_list)
    df['green'] = df['category'].apply(lambda x: 'green' in x)
    

    结果:

    user category green
    0 Bob ['green', 'red'] True
    1 Jane ['blue'] False
    2 Theresa ['green'] True
    3 Alice ['yellow', 'purple', 'green', 'brown'] True
    4 John [] False

    【讨论】:

      猜你喜欢
      • 2015-04-25
      • 2021-12-30
      • 2023-01-04
      • 2017-10-28
      • 2017-01-11
      • 2016-02-10
      • 2021-05-19
      • 2016-12-30
      • 2021-10-04
      相关资源
      最近更新 更多