【问题标题】:Loop over each row of a data frame and add an element to the data frame based on a condition循环遍历数据框的每一行,并根据条件向数据框添加一个元素
【发布时间】:2021-01-17 15:26:17
【问题描述】:

我想遍历数据框的每一行,如果列和列表中的字符串匹配,我会在新列中添加一个元素。 在此示例中,我想添加一个新列来对产品进行分类。因此,如果该列的一行与列表中的一个匹配,则类别可以是“饮料”或“食品”,如果不匹配,则类别将是其他。

list_drinks={'Water','Juice','Tea'}
list_food={'Apple','Orange'}
data = {'Price':  ['1', '5','3'], 'Product': ['Juice','book', Pen]}
for (i,j) in itertools.zip_longest(list_drinks,list_food):
    for index in data.index: 
        if(j in data.loc[index,'product']):
            data["Category"] = "Food"
        elif(i in data.loc[index,'product']):
            data["Category"] ="drinks"
        else:
            data["Category"]="Other"
           

输出将是:

Price  Product Category
 1      Juice    drinks
 5      book     Other
 3      Pen      Other

我的问题主要是我不知道如何匹配列表和行之间的模式。我也试过: str.contains 但它不起作用。

【问题讨论】:

    标签: python pandas dataframe loops for-loop


    【解决方案1】:

    无需循环。您可以使用.isin()np.select() 根据条件返回结果。见以下代码:

    import pandas as pd
    import numpy as np
    list_drinks=['Water','Juice','Tea']
    list_food=['Apple','Orange']
    data = {'Price':  ['1', '5','3'],
        'Product': ['Juice','book','Pen']}
    df = pd.DataFrame(data)
    df['Category'] = np.select([(df['Product'].isin(list_drinks)),
                   (df['Product'].isin(list_food))],
                  ['drinks',
                  'food'], 'Other')
    df
    Out[1]: 
      Price Product Category
    0     1   Juice   drinks
    1     5    book    Other
    2     3     Pen    Other
    

    下面,我将代码分解为更详细的代码,以便您了解它是如何工作的。我也对你的评论略有改变。我通过使用列表理解和in 检查列表中的值是否在数据框中的值的子字符串中。为了提高匹配率,我还比较了全部小写和.lower()

    import pandas as pd
    import numpy as np
    list_drinks=['Water','Juice','Tea']
    list_food=['Apple','Orange']
    data = {'Price':  ['1', '5','3'],
        'Product': ['green Juice','book','oRange you gonna say banana']}
    df = pd.DataFrame(data)
    c1 = (df['Product'].apply(lambda x: len([y for y in list_drinks if y.lower() in x.lower()]) > 0))
    c2 = (df['Product'].apply(lambda x: len([y for y in list_food if y.lower() in x.lower()]) > 0))
    r1 = 'drinks'
    r2 = 'food'
    
    conditions = [c1,c2]
    results= [r1,r2]
    
    df['Category'] = np.select(conditions, results, 'Other')
    df
    Out[1]: 
      Price                      Product Category
    0     1                  green Juice   drinks
    1     5                         book    Other
    2     3  oRange you gonna say banana     food
    

    【讨论】:

    • 嗨@David,感谢您的回答。我在更大的数据框上进行了尝试,但所有行都被归类为其他行。当您使用“isin”时,它是否匹配列表中的部分字符串,或者它是否必须是完美匹配。假设我的数据框产品中有:“green Juice”,它会被归类为“Juice”还是“others”?
    • @thephoenix 检查新代码。使用第二个块,而不是第一个。
    • 嗨@David,我还有一个问题。我将代码用于不同的数据框,当我使用 np.select 语句时出现此错误:“TypeError:condlist 中的无效条目 0:应该是布尔 ndarray。”你知道可能是什么问题吗?
    • 请参阅:stackoverflow.com/questions/57316346/…。 df['Product'].fillna('')
    • 我试过 df['Product'].fillna('').apply(lambda x: len([y for y in list_food if y.lower() in x.lower()]) > 0)) 但它仍然无法正常工作@David
    【解决方案2】:

    这是另一种选择-

    import itertools
    import pandas as pd
    
    list_drinks={'Water','Juice','Tea'}
    list_food={'Apple','Orange'}
    data = pd.DataFrame({'Price':  ['1', '5','3'], 'Product': ['Juice','book', 'Pen']})
    category = list()
    for prod in data['Product']: 
        if prod in list_food:
            category.append("Food")
        elif prod in list_drinks:
            category.append("drinks")
        else:
            category.append("Other")
    data['Category']= category
    print(data)
    

    输出-

    Price  Product Category
     1      Juice    drinks
     5      book     Other
     3      Pen      Other
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 2018-03-16
      • 1970-01-01
      • 2021-03-18
      相关资源
      最近更新 更多