在pandas的apply方法中,基于条件复制行。

6
这是我的df的一个示例:
pd.DataFrame([["1", "2"], ["1", "2"], ["3", "other_value"]],
                     columns=["a", "b"])
    a   b
0   1   2
1   1   2
2   3   other_value

我希望能够达到这个目标:

pd.DataFrame([["1", "2"], ["1", "2"], ["3", "other_value"], ["3", "row_duplicated_with_edits_in_this_column"]],
                     columns=["a", "b"])
    a   b
0   1   2
1   1   2
2   3   other_value
3   3   row_duplicated_with_edits_in_this_column

使用apply方法,并进行一些检查(为了简单起见,我不包括这些检查),但在某些条件下,对于apply函数中的某些行,复制该行,对该行进行编辑,并将两行插入df中。

因此,像这样:

def f(row):
   if condition:
      row["a"] = 3
   elif condition:
      row["a"] = 4
   elif condition:
      row_duplicated = row.copy()
      row_duplicated["a"] = 5 # I need also this row to be included in the df

   return row
df.apply(f, axis=1)

我不想在我的类中存储重复的行并在最后添加它们。我想实时处理它们。
我看到了这个 pandas: apply function to DataFrame that can return multiple rows,但我不确定groupby是否能帮助我。
谢谢
3个回答

3

以下是一种使用 df.iterrows 的方法,它在列表推导式中被使用。你需要将行添加到循环中,然后进行连接。

def func(row):
   if row['a'] == "3":
        row2 = row.copy()
        # make edits to row2
        return pd.concat([row, row2], axis=1)
   return row

pd.concat([func(row) for _, row in df.iterrows()], ignore_index=True, axis=1).T

   a            b
0  1            2
1  1            2
2  3  other_value
3  3  other_value

我发现在我的情况下,不使用ignore_index=True更好,因为之后我要合并两个数据框。


谢谢,这个可行,我更喜欢使用apply(),因为我使用了df.query().apply().combine_first(),但是即使进行了小的修改,你的解决方案也可以工作,而无需将数据存储在任何地方。 - Claudiu Creanga

2

您的逻辑似乎大部分可向量化。由于输出中的行顺序似乎很重要,您可以将默认的RangeIndex增加0.5,然后使用sort_index

def row_appends(x):
    newrows = x.loc[x['a'].isin(['3', '4', '5'])].copy()
    newrows.loc[x['a'] == '3', 'b'] = 10  # make conditional edit
    newrows.loc[x['a'] == '4', 'b'] = 20  # make conditional edit
    newrows.index = newrows.index + 0.5
    return newrows

res = pd.concat([df, df.pipe(row_appends)])\
        .sort_index().reset_index(drop=True)

print(res)

   a            b
0  1            2
1  1            2
2  3  other_value
3  3           10

1
我会将其矢量化,逐类别进行处理:
df[df_condition_1]["a"] = 3
df[df_condition_2]["a"] = 4

duplicates = df[df_condition_3] # somehow we store it ?     
duplicates["a"] = 5 

#then 
df.join(duplicates, how='outer')

这个解决方案是否符合您的需求?

1
谢谢,这样做可能会更快,但是我的条件很多,而且分布在多个函数中,这种解决方案会使代码变得不太易读。 - Claudiu Creanga

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接