【问题标题】:Iterating through dataframe and updating based on dictionary conditions遍历数据框并根据字典条件进行更新
【发布时间】:2019-04-15 04:40:24
【问题描述】:

我需要处理以下 xlsx 文件:

我想遍历数据框,如果列 ITEM CODE 包含字典键,我想检查同一行是否包含字典值 [0](元组中的第一个位置),如果包含我想将字典值1(元组中的第二个位置)插入另一个名为 SKU 的列中

数据框:#df3 = df2.append(df1)

catp = {"2755":(('24','002'),('25','003'),('26','003'),('27','004'),('28','005'),('29','006'),('30','007'),('31','008'),
                ('32','009'),('32','010'),('33','011'),('34','012'),('35','013'),('36','014')),
        "2513":(('38','002'),('40','003'),('42','004'),('44','005'),('46','006'),('48','007'),('50','008'),('52','009'),
               ('54','010'))}

for i, row in df3.iterrows():
    if catp.key() in df3['ITEM CODE'][i] and catp.value()[0] in df3['TG'][i]:
            codmarime = catp.value()[1]
            df3['SKU'][i] = '20'+df3['ITEM CODE'][i]+[i]+codmarime

    else:
        df3['SKU'][i] = '20'+df3['ITEM CODE'][i]+'???'

如果找到 2755 和 24 SKU = '202755638002'

如果找到 2513 和 44 SKU = '202513123005'

输出 xlsx

【问题讨论】:

  • 还提供示例数据框
  • 可以吗? imgur.com/enrKxa6 ,也插入到帖子中
  • 您提供了一张图片。请提供文本内容。
  • 您的代码在 ifelse 变体的末尾都包含 codmarime = ''。这些替换的目的是什么?
  • 编辑和删除 codmarime = ' ' 。这是为了在某个时候进行测试。

标签: python pandas xlsx


【解决方案1】:

由于您未能提供文本数据来创建至少一个 DataFrame 片段, 我从你的图片中复制了 3 行,创建了我的测试 DataFrame:

df3 = pd.DataFrame(data=[
    [ '1513452', 'AVRO D2', '685', 'BLACK/BLACK/ANTRACITE', '24', 929.95, '8052644627565' ],
    [ '2513452', 'AVRO D2', '685', 'BLACK/BLACK/ANTRACITE', '21', 929.95, '8052644627565' ],
    [ '2755126', 'AMELIA',  'Y17', 'DARK-DENIM',            '24', 179.95, '8052644627565' ]],
    columns=[ 'ITEM CODE', 'ITEM', 'COLOR', 'COLOR CODE', 'TG', 'PRICE', 'EAN' ])

详情:

  • 第一行在ITEM CODE 列中不包含任何catp 键。
  • 第二行:ITEM CODE 包含您的其中一个代码 (2513) 但对于 TG2513 键下保存的列没有元组包含第一个元素 == 21
  • 第三行:ITEM CODE 包含您的代码之一 (2755),TG == 242755 下保存的元组中,有一个 == 24

然后我们要定义几个辅助函数:

def findContainedCodeAndVal(dct, str):
    for eachKey in dct.keys():
        if str.find(eachKey) >= 0:
            return (eachKey, dct[eachKey])
    else:
        return (None, None)

此函数尝试在dct 中查找包含在str 中的键。 它返回一个 2 元组,其中包含从 dct 找到的键和关联值。

def find2ndElem(tuples, str):
    for tpl in tuples:
        if tpl[0] == str:
            return tpl[1]
    else:
        return ''

这个函数检查来自tuples的每个元组是否是它的第一个元素 == str 并返回此元组的第二个元素。

最后定义的函数是应用于每一行的函数 从你的数据框。它返回要保存在SKU 列中的值:

def fn(row):
    ind = row.name  # Read row index
    iCode = row['ITEM CODE']
    k, val = findContainedCodeAndVal(catp, iCode)
    codmarime = ''
    if k:
        tg = row.TG
        codmarime = find2ndElem(val, tg)
    if codmarime == '':
        codmarime = '???'
    return f'20/{iCode}/{ind}/{codmarime}'

请注意,它使用您的 catp 字典。

出于演示目的,我在返回值中引入了附加 斜线,分隔相邻部分。在目标版本中删除它们。

最后要做的是计算 DataFrame 的 SKU 列, 将fn 函数应用于df3 的每一行并将结果保存在 SKU专栏:

df3['SKU'] = df3.apply(fn, axis=1)

当您打印 DataFrame(包含我的测试数据)时,SKU 列将 包含:

20/1513452/0/???
20/2513452/1/???
20/2755126/2/002

【讨论】:

  • 您好,您的代码有问题,当单元格为空时:----> 4 df3['SKU'] = df3.apply(fn, axis=1) AttributeError: ( "'float' 对象没有属性 'find'", '发生在索引 0')
  • 似乎错误发生在 if str.find(eachKey) >= 0: 因为 str 要么是 NaN i> 或 None (检查是哪种情况)。为了避免这个错误,在for eachKey in dct.keys():之前你应该检查str。如果它为空(NaNNone),则该函数应返回 (None, None)。其他解决方案是将所有 None / NaN 值替换为空字符串 (fillna())。如果提供了某个值,则应执行此函数的其余部分。其他解决方案是将 None 值替换为空字符串 (fillna())。
【解决方案2】:

我无法正确理解这个问题,但只是更正了我在您的代码中看到的错误:

if catp.key() in df3['ITEM CODE'][i] and catp.value()[0] in df3['TG'][i]:

这是不正确的。

如果我了解最终目标,我会采取不同的方法

for key in catp.keys():
     xdf = df3.loc[(df3['SKU'].astype(str).contains(key)) & (df3['SKU'].astype(str).contains(catp[key][0])]
     if len(xdf)>0:
         for i, row in xdf.iterrows():
                codmarime = catp[key][1]
                df3.at[i,'SKU'] = '20'+row['ITEM CODE'][i]+[i]+codmarime

【讨论】:

    猜你喜欢
    • 2020-01-19
    • 2020-04-21
    • 2022-01-03
    • 2018-12-24
    • 2023-01-26
    • 1970-01-01
    • 2021-03-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多