在具有循环或 lambda 的多个数据帧中添加具有相同字符串值的列的更有效方法?

Posted

技术标签:

【中文标题】在具有循环或 lambda 的多个数据帧中添加具有相同字符串值的列的更有效方法?【英文标题】:More efficient way to add columns with same string values in multiple dataframes with loops or lambdas? 【发布时间】:2020-10-28 00:11:27 【问题描述】:

我想在我的 8 个相似数据框中的每一个中添加一个新列 Category。 此列中的值相同,它们也是 df 名称,如本例中的df1_p8。 我用过:

In:     df61_p8.insert(3,"Category","df61_p8", True)
# or simply, df61_p8['Category']='df61_p8'

Out:
        code    violation_description                                            Category
89491   9-1-503 Defective or obstructed duct system one- building                df61_p8
102045  9-1-503 Defective or obstructed duct system one- building                df61_p8
103369  9-1-503 Defective or obstructed duct system one- building                df61_p8
130440  9-1-502 Failure to maintain at least one (1) elevator                    df61_p8
132446  9-1-503 Defective or obstructed duct system one-  building               df61_p8

最终,我想将这 8 个数据帧附加/连接到一个数据帧中。

我想知道是否有更有效的方法来做到这一点,而不是在每个数据帧上一个一个地使用 .insert。 循环或 lambda 之类的东西。作为初学者,我不确定如何在我的情况下应用它们?谢谢。

append_alldfs = []
x=[df61_p1,df61_p2,df61_p3,df61_p4,df61_p5,df61_p6,df61_p7,df61_p8]
lambdafunc = lambda x: x.insert(3,"Category","x",True)

【问题讨论】:

【参考方案1】:
def add_column(df, col_name, col_value):
  return df.insert(loc=-1, column=col_name, value=col_value, allow_duplicates = False)

df_list = [........]
col_name = ... 
col_value = .... # copy column (Category) values

res = map(lambda df: add_column(df, col_name, col_value), df_list)
list(res)

【讨论】:

你的答案正是我所希望的......但是,我无法让它工作,因为它给了我一个空输出 def add_column(df, col_name, col_value): return df.insert(loc=-1, column=col_name, value=col_value, allow_duplicates = False) df_list = [df61_p1,df61_p2,df61_p3,df61_p4] col_name = 'Category' col_value = ['df61_p1','df61_p2','df61_p3 ','df61_p4'] 结果 = map(lambda df: add_column(df, col_name, col_value), df_list) 结果 是的,使用list(map_object),我已经更新了答案 map(),比使用循环更高效【参考方案2】:

您可以使用pd.concatkeys 参数,然后使用reset_index

pd.concat([df0,df1,df2,df3], keys=['df0', 'df1', 'df2', 'df3']).reset_index(level=0) 

MCVE:

df0  = pd.DataFrame(np.ones((3,3)), columns=[*'ABC'])
df1  = pd.DataFrame(np.zeros((3,3)), columns=[*'ABC'])
df2  = pd.DataFrame(np.zeros((3,3))+3, columns=[*'ABC'])
df3  = pd.DataFrame(np.zeros((3,3))+4, columns=[*'ABC'])

df_out = pd.concat([df0,df1,df2,df3], keys=['df0', 'df1', 'df2', 'df3']).reset_index(level=0)
df_out

输出:

  level_0    A    B    C
0     df0  1.0  1.0  1.0
1     df0  1.0  1.0  1.0
2     df0  1.0  1.0  1.0
0     df1  0.0  0.0  0.0
1     df1  0.0  0.0  0.0
2     df1  0.0  0.0  0.0
0     df2  3.0  3.0  3.0
1     df2  3.0  3.0  3.0
2     df2  3.0  3.0  3.0
0     df3  4.0  4.0  4.0
1     df3  4.0  4.0  4.0
2     df3  4.0  4.0  4.0

【讨论】:

@bluetail 是的,这会创建一个 pd.MultiIndex 然后你在一个级别上 reset_index。【参考方案3】:

保持简单明了。

for col_val, df in [
   ('df61_p1', df61_p1),
   ('df61_p2', df61_p2),
   ('df61_p3', df61_p3),
   ('df61_p4', df61_p4),
   ('df61_p5', df61_p5),
   ('df61_p6', df61_p6),
   ('df61_p7', df61_p7),
   ('df61_p8', df61_p8),
]:
    df['Category'] = col_val

虽然there are certainly more 'meta-programming-ey' ways of accomplishing the same task,但这些通常相当复杂,更难理解和重构。

但是,考虑到这段代码的结构,我想在你到达这一点之前,有一些方法可以解决这个问题。

例如,这些数据帧是在什么时候被拆分的?也许通过从不使用单独的 DataFrames [将原始数据帧保持在一起/在开始时 concat](并根据需要使用 apply、groupby、pivot 和 melt 操作),您可以完全避免这个问题。

【讨论】:

这超出了我的 Coursera 练习范围。我问这个问题只是为了学习如何去做。 :) 感谢您的回答,我无法决定是选择您的还是 concat 海报以获得最佳解决方案!

以上是关于在具有循环或 lambda 的多个数据帧中添加具有相同字符串值的列的更有效方法?的主要内容,如果未能解决你的问题,请参考以下文章

Keras:具有多个参数的 Lambda 层函数

find_if 中具有多个参数的 Lambda

获取具有特定数量的重复值的行

合并具有不同列名但定义相同的多个CSV

附加到数据帧中特定值的 for 循环中的向量

在具有多个 if 语句的 Pandas Lambda 函数中使用 Apply