如果条件满足,则重复数据帧的行,并更改一个值的值

时间:2020-12-23 21:21:27

标签: python

我有一个数据框:

import pandas as pd
df = pd.DataFrame(
{
    "Qty": [1,2,2,4,5,4,3],
    "Date": ['2020-12-16', '2020-12-17', '2020-12-18', '2020-12-19', '2020-12-20', '2020-12-21', '2020-12-22'],
    "Item": ['22-A', 'R-22-A', '33-CDE', 'R-33-CDE', '55-A', '22-AB', '55-AB'],
    "Price": [1.1, 2.2, 2.2, 4.4, 5.5, 4.4, 3.3]
})

我试图复制 Item 后缀具有 2 个或更多字符的每一行,然后更改 Item 的值。例如,包含“22-AB”的行将变成两行。在第一行,项目将是“22-A”,在第二行,它将是“22-B”。 只有当项目编号(无后缀)在“干净”列表中时,才应执行所有这些操作。

这是我要实现的伪代码:
干净的项目列表 = ['11', '22', '33']
对于每一行,检查 df["Item"] 的子字符串是否在干净列表中。
如果没有:
跳过一行并保持原样
如果是:
检查 len(suffix) >= 2
如果没有:
跳过一行并保持原样
如果是:
将项目(11、22 或 33)和后缀分开
对于后缀中的字符:
newitem = concat item + char
复制该行,用 newitem 替换旧项目
如果数字以 R- 开头,则再次添加 R-

所需的输出:

df2 = pd.DataFrame(
{
    "Qty": [1,2,2,2,2,4,4,4,5,4,4,3,3],
    "Date": ['2020-12-16', '2020-12-17', '2020-12-18', '2020-12-18', '2020-12-18', '2020-12-19', '2020-12-19', '2020-12-19', '2020-12-20', '2020-12-21', '2020-12-21', '2020-12-22', '2020-12-22'],
    "Item": ['22-A', 'R-22-A', '33-C', '33-D', '33-E', 'R-33-C', 'R-33-D', 'R-33-E', '55-A', '22-A', '22-B', '55-A', '55-B'],
    "Price": [1.1, 2.2, 2.2, 2.2, 2.2, 4.4, 4.4, 4.4, 5.5, 4.4, 4.4, 3.3, 3.3]
})

到目前为止我想出了什么:

mains = ['11', '22', '33']
for i in df["Item"]:
    iptrn = re.compile(r'\d{2}')
    optrn = re.compile('(?<=[0-9]-).*')
    item = bptrn.search(i).group(0)
    option = optrn.search(i).group(0)
    if item in mains:
        for o in option:
            combo = item + "-" + o
            print(combo)

我无法弄清楚实际复制行的最后一步。我试过这个:df = df.loc[df.index.repeat(1)].assign(Item=combo, num=len(option)-1).reset_index(drop=True),但它没有正确替换项目

1 个答案:

答案 0 :(得分:0)

你可以使用pandas操作来完成这里的工作

似乎第一步是用pandas字符串方法将项目代码的两部分分开(这里,使用extractexpand=True

>>> item_code = df['Item'].str.extract('(?P<ic1>R?-?\d+)-+(?P<ic2>\w+)', expand=True)
>>> item_code
    ic1  ic2
0    22    A
1  R-22    A
2    33  CDE
3  R-33  CDE
4    55    A
5    22   AB
6    55   AB

您可以将这些列直接添加到 df - 我只是在上面包含了该片段以向您展示提取操作的输出。

>>> df = df.join(df['Item'].str.extract('(?P<ic1>R?-?\d+)-+(?P<ic2>\w+)', expand=True))
>>> df
   Qty        Date      Item  Price   ic1  ic2
0    1  2020-12-16      22-A    1.1    22    A
1    2  2020-12-17    R-22-A    2.2  R-22    A
2    2  2020-12-18    33-CDE    2.2    33  CDE
3    4  2020-12-19  R-33-CDE    4.4  R-33  CDE
4    5  2020-12-20      55-A    5.5    55    A
5    4  2020-12-21     22-AB    4.4    22   AB
6    3  2020-12-22     55-AB    3.3    55   AB

接下来,我将构建一个 python 数据结构,并在最后将其转换为数据帧,而不是尝试插入行或更改现有行。

data = []
for row in df.itertuples(index=False):
    for character in row.ic2:
        data.append({
          'Date': row.Date, 
          'Qty': row.Qty, 
          'Price': row.Price,
          'Item': f'{row.ic1}-{character}'
        })

newdf = pd.DataFrame(data)

新的数据框看起来像这样

>>> newdf
          Date  Qty  Price    Item
0   2020-12-16    1    1.1    22-A
1   2020-12-17    2    2.2  R-22-A
2   2020-12-18    2    2.2    33-C
3   2020-12-18    2    2.2    33-D
4   2020-12-18    2    2.2    33-E
5   2020-12-19    4    4.4  R-33-C
6   2020-12-19    4    4.4  R-33-D
7   2020-12-19    4    4.4  R-33-E
8   2020-12-20    5    5.5    55-A
9   2020-12-21    4    4.4    22-A
10  2020-12-21    4    4.4    22-B
11  2020-12-22    3    3.3    55-A
12  2020-12-22    3    3.3    55-B

相关问题