【问题标题】:Alternative way to merge two dataframes in python在python中合并两个数据框的替代方法
【发布时间】:2020-11-05 22:02:37
【问题描述】:

让我们举一个简单的例子。我有第一个数据框:

df = pd.DataFrame(dict(Name=['abc','def','ghi'],NoMatter=['X','X','X']))
df
  Name NoMatter
0  abc        X
1  def        X
2  ghi        X

由于某些原因,我想使用一个 for 循环,将列值添加到 df 并从另一个数据帧中进行一些处理,每次迭代都会发生变化:

# strucutre of for loop I would like to use :
for i in range(something) :
    add the column Value to df from df_value
    other treatment not usefull here

# appearance of df_value (which change at each iteration of the for loop) :
  Name  Value
0  abc      1
1  def      2
2  ghi      3

但是,我不希望使用合并,因为这需要在添加当前迭代之一之前删除在上一次迭代中添加的列值。有没有一种方法可以通过这样的分配将 Value 列添加到 df :

df['Value'] = XXX

预期输出:

  Name NoMatter  Value
0  abc        X      1
1  def        X      2
2  ghi        X      3

[编辑]

我不想使用合并,因为在 for 循环的第四次迭代中,df 将包含列:

名称 NoMatter Value1 Value2 Value3 Value4

而我只想拥有:

名称NoMatter Value4

我可以每次都删除上一列,但似乎效率不高。这就是为什么我只是在寻找一种方法来为 Value 列分配值,而不是添加列。就像 Excel 中的等效 vlookup 函数从 df_value 数据应用于 df。

【问题讨论】:

  • 您的预期输出是什么?不清楚。
  • @Serge Ballesta,我只想将 Value 列添加到 df,没有任何其他处理(我在帖子中谈到了一些处理以证明使用 for 循环的合理性)。感谢您的帮助
  • 如果你只想合并特定的列,那么df2 = pd.merge(df[['Name','Value']], df1, how='left',on='Name'])
  • @David Erickson 谢谢,但没有:如果我这样做,在第二次迭代中,我将获得第一次迭代和第二次迭代的列值,我想替换值列。我可以使用合并,然后删除以前的值列,但效率不高

标签: python pandas dataframe merge


【解决方案1】:

也许不是最好的方法,但此解决方案在每次迭代时都有效并替换了 Value 列(无需在每次新迭代之前删除 Value 列):

# similar to Excel vlookup function
def vlookup(df,ref,col_ref,col_goal):
    return pd.DataFrame(df[df.apply(lambda x: ref == x[col_ref],axis=1)][col_goal]).iloc[0,0]

df['Value'] = df['Name'].apply(lambda x : vlookup(df_value,x,'Name','Value'))

#Output : 

  Name NoMatter  Value
0  abc        X      1
1  def        X      2
2  ghi        X      3

【讨论】:

    【解决方案2】:

    正确的方法是@UmerRana's answer,因为迭代数据帧的性能很差。如果您确实必须这样做,可以寻址单个单元格,但不要假装我建议您这样做:

    df = pd.DataFrame(dict(Name=['abc','def','ghi'],NoMatter=['X','X','X']))
    df1 = pd.DataFrame(dict(Name=['abc','def','ghi'],Value=[1,2,3]))
    df['Value'] = 0    # initialize a new column of integers (hence the 0)
    ix = df.columns.get_loc('Value')
    for i in range(len(df)):                    # perf is terrible!
        df.iloc[i, ix] = df1['Value'][i]
    

    看到您的示例代码后,如果您无法避免循环,我认为这将是不太糟糕的方法:

    newcol = np.zeros(something, dtype='int')  # set the correct type
    for i in range(something):
        #compute a value
        newcol[i] = value_for_i_iteration
    df['Value'] = newcol                       # assign the array to the new column
    

    【讨论】:

      【解决方案3】:

      这是您问题的解决方案。

      import pandas as pd
      df = pd.DataFrame(dict(Name=['abc','def','ghi'],NoMatter=['X','X','X']))
      df1 = pd.DataFrame(dict(Name=['abc','def','ghi'],Value=[1,2,3]))
      new_df=pd.merge(df, df1, on='Name')
      new_df
      

      【讨论】:

      • 感谢您的帮助,但使用合并我需要在每次迭代中删除之前的值列
      • 我不明白你的意思是在每次迭代中删除以前的值列。你能通过应用这个来发送你所面临的问题吗?
      • del df['Value'] del 列在下一次迭代前循环结束
      • 这是我在帖子中建议的方式,但我正在寻找一种更有效的方式。合并然后删除并不是很有效
      • 那么有一种方法可以通过 if 语句来实现。如果此列已经存在,请将其替换为新的
      【解决方案4】:

      加入数据框的三种方法

      df1.append(df2) # 将df1中的行添加到df2的末尾(列应该相同)

      pd.concat([df1, df2],axis=1) # 将df1中的列添加到df2的末尾(行应该相同)

      df1.join(df2,on=col1,how='inner') # SQL 风格将 df1 中的列与 on 的列连接起来 df2 其中 col 的行具有相同的值。怎么可能是“左”、“右”之一,

      【讨论】:

      • 感谢您的帮助,但在所有这些情况下,我都需要在每次迭代中删除之前的值列
      猜你喜欢
      • 1970-01-01
      • 2019-07-26
      • 1970-01-01
      • 1970-01-01
      • 2021-05-30
      • 2021-05-24
      • 2016-03-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多