【问题标题】:How to merge two dataframes and return data from another column in new column only if there is match?仅当匹配时,如何合并两个数据框并从新列中的另一列返回数据?
【发布时间】:2018-11-14 14:50:35
【问题描述】:

我有两个像这样的 df:

df1:

id
1
2


df2:

id    value
2       a
3       b

如何合并这两个数据框,如果匹配,则仅在新列中返回来自value 列的数据?

new_merged_df

id   value   new_value
1
2     a         a
3     b

【问题讨论】:

    标签: python-3.x pandas dataframe merge


    【解决方案1】:

    您可以使用@JJFord3 设置试试这个:

    import pandas
    
    df1 = pandas.DataFrame(index=[1,2])
    df2 = pandas.DataFrame({'value' : ['a','b']},index=[2,3])
    
    #Use isin to create new_value   
    df2['new_value'] = df2['value'].where(df2.index.isin(df1.index))
    #Use reindex with union to rebuild dataframe with both indexes
    df2.reindex(df1.index.union(df2.index))
    

    输出:

      value new_value
    1   NaN       NaN
    2     a         a
    3     b       NaN
    

    【讨论】:

      【解决方案2】:
      import pandas
      
      df1 = pandas.DataFrame(index=[1,2])
      df2 = pandas.DataFrame({'value' : ['a','b']},index=[2,3])
      
      new_merged_df_outer = df1.merge(df2,how='outer',left_index=True,right_index=True)
      new_merged_df_inner = df1.merge(df2,how='inner',left_index=True,right_index=True)
      new_merged_df_inner.rename(columns={'value':'new_value'})
      new_merged_df = new_merged_df_outer.merge(new_merged_df_inner,how='left',left_index=True,right_index=True)
      

      首先,创建一个外部合并以保留所有索引。 然后创建一个内部合并只得到重叠。 然后将内部合并合并回外部合并以获得所需的列设置。

      【讨论】:

      • 可能有更有效的方法来做到这一点,但考虑到您想要内部和外部表示,我认为这是获得所需结果的最直接方式。
      【解决方案3】:

      您可以使用full outer join

      让我们使用案例类对数据进行建模:

      case class MyClass1(id: String)
      case class MyClass2(id: String, value: String)
      
      //  this one for the result type
      case class MyClass3(id: String, value: Option[String] = None, value2: Option[String] = None)
      

      创建一些输入:

      val input1: Dataset[MyClass1] = ...
      val input2: Dataset[MyClass2] = ...
      

      加入您的数据:

      import scala.implicits._
      val joined = input1.as("1").joinWith(input2.as("2"), $"1.id" === $"2.id", "full_outer")
      
      joined map {
        case (left, null) if left != null => MyClass3(left.id)
        case (null, right) if right != null => MyClass3(right.id, Some(right.value))
        case (left, right) => MyClass3(left.id, Some(right.value), Some(right.value))
      }
      

      【讨论】:

      • 这是 python pandas,不是 scala
      【解决方案4】:

      DataFrame.merge 在参数indicator 中有

      如果为 True,则在输出 DataFrame 中添加一个名为“_merge”的列,其中包含有关每行来源的信息。

      这可以用来检查是否匹配

      import pandas as pd
      
      df1 = pd.DataFrame(index=[1,2])
      df2 = pd.DataFrame({'value' : ['a','b']},index=[2,3])
      
      # creates a new column `_merge` with values `right_only`, `left_only` or `both`
      merged = df1.merge(df2, how='outer', right_index=True, left_index=True, indicator=True) 
      merged['new_value'] = merged.loc[(merged['_merge'] == 'both'), 'value']
      merged = merged.drop('_merge', axis=1)
      

      【讨论】:

        【解决方案5】:

        使用mergeisin

        df = df1.merge(df2,on='id',how='outer')
        
        id_value = df2.loc[df2['id'].isin(df1.id.tolist()),'id'].unique()
        mask = df['id'].isin(id_value)
        df.loc[mask,'new_value'] = df.loc[mask,'value']
        # alternative df['new_value'] = np.where(mask, df['value'], np.nan)    
        
        print(df)
           id value new_value
        0   1   NaN       NaN
        1   2     a         a
        2   3     b       NaN
        

        【讨论】:

          猜你喜欢
          • 2021-07-22
          • 2018-06-25
          • 2013-05-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多