【问题标题】:Adding values to new Pandas dataframe column based on partial string contents of existing column根据现有列的部分字符串内容向新的 Pandas 数据框列添加值
【发布时间】:2017-11-15 02:01:09
【问题描述】:

我使用 Python Pandas 将数据存储为数据框。在这些列中,我有一个“产品”列,其中包含品牌名称和型号(例如 Nike Air Jordan、Adidas Gazelle)。我想创建一个只包含品牌(例如 Nike、Adidas)的新列,稍后我将在 groupby 中使用它来汇总数据。 根据我的研究,我相信 contains 和 regex 可以用来做到这一点。但是,实施并没有奏效。我还看到了不同的方法,一些使用“for i in range”,而另一些则在一行代码中使用它作为替换。

import pandas as pd
import numpy as np

shoes_df = pd.DataFrame({'Product':['Nike vaporfly', 'Nike Jordans', 'Adidas supernova', 'Asics Kayano', 'Asics GT2010', 'Adidas gazelle', 'Nike air max',
                                  'Nike Lebron'], 'Unit sales':[1500, 1600,
2341, 1345, 4523, 2345, 1634, 3129]})

shoes_df['Brand'] = np.where(shoes_df['Product'].str.contains('Nike.*|Adidas.*').any(), 'Nike|Adidas', np.nan)

print(shoes_df)

这是我尝试使用“for i in range”的方法,但也没有用。在这里,我收到错误“TypeError:'Series' 对象是可变的,因此它们不能被散列”

shoes_df = pd.DataFrame({'Product':['Nike vaporfly', 'Nike Jordans', 'Adidas supernova', 'Asics Kayano', 'Asics GT2010', 'Adidas gazelle', 'Nike air max',
                                  'Nike Lebron'], 'Unit sales':[1500, 1600, 2341, 1345, 4523,
                                   2345, 1634, 3129]})

for i in shoes_df.iterrows():
    if shoes_df['Product'].str.contains('Nike').any():
        shoes_df.set_value(i, 'Brand', 'Nike')
    elif shoes_df['Product'].str.contains('Adidas').any():
        shoes_df.set_value(i, 'Brand', 'Adidas')
    elif shoes_df['Product'].str.contains('Asics').any():
        shoes_df.set_value(i, 'Brand', 'Asics')
    else:
        shoes_df.set_value(i, 'Brand', np.nan)

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    IIUC:

    shoes_df['brand'] = shoes_df.Product.str.extract(pat='(Nike|Adidas|Asics)',expand=False)
    

    输出:

                Product  Unit sales   brand
    0     Nike vaporfly        1500    Nike
    1      Nike Jordans        1600    Nike
    2  Adidas supernova        2341  Adidas
    3      Asics Kayano        1345   Asics
    4      Asics GT2010        4523   Asics
    5    Adidas gazelle        2345  Adidas
    6      Nike air max        1634    Nike
    7       Nike Lebron        3129    Nike
    

    【讨论】:

    • 这成功了,而且很容易理解。我错过了使用提取物。谢谢你。当品牌不是第一个词并且仍然有效时,也进行了测试。
    【解决方案2】:

    选项 1(艰难的方式)
    str.extract

    brands = ['Nike', 'Adidas', 'Asics']
    df['Brand'] = df.Product.str.extract('({})'.format('|'.join(brands)), expand=True)
    
    df
    
                Product  Unit sales   Brand
    0     Nike vaporfly        1500    Nike
    1      Nike Jordans        1600    Nike
    2  Adidas supernova        2341  Adidas
    3      Asics Kayano        1345   Asics
    4      Asics GT2010        4523   Asics
    5    Adidas gazelle        2345  Adidas
    6      Nike air max        1634    Nike
    7       Nike Lebron        3129    Nike
    

    选项 2(稍微简单一些)
    str.split

    df['Brand'] = df.Product.str.split().str[0]
    df
    
                Product  Unit sales   Brand
    0     Nike vaporfly        1500    Nike
    1      Nike Jordans        1600    Nike
    2  Adidas supernova        2341  Adidas
    3      Asics Kayano        1345   Asics
    4      Asics GT2010        4523   Asics
    5    Adidas gazelle        2345  Adidas
    6      Nike air max        1634    Nike
    7       Nike Lebron        3129    Nike
    

    您可以稍微扩展一下,用NaN 替换不在brands 中的任何内容:

    df['Brand'] = np.where(df.Brand.isin(brands), df.Brand, np.nan)
    

    【讨论】:

    • 谢谢。第一个在不同的迭代中工作。当品牌是第一个词时,选项 2 有效,但如果品牌在字符串中较晚出现,则返回另一个词。无论品牌在哪里,选项 1 都有效。
    • @skibbereen 这就是为什么我在选项 2 之前提供选项 1 ;/
    • @cᴏʟᴅsᴘᴇᴇᴅ - 骗子,stackoverflow.com/q/47292599/2901002,请查找匹配或未解决的问题。
    【解决方案3】:

    如果您可以假设品牌始终是第一个词,那么该解决方案可让您灵活地捕捉已知列表之外的品牌,因此只需添加它以引起兴趣:

    shoes_df['Product'].str.extract('^([^\s]+)\s')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-26
      • 2015-11-19
      • 1970-01-01
      • 1970-01-01
      • 2018-08-13
      • 2020-05-04
      相关资源
      最近更新 更多