【问题标题】:pandas pivot and join in two dataframes熊猫枢轴并加入两个数据框
【发布时间】:2019-01-07 20:20:27
【问题描述】:

我有两个数据框:

df1
   mag   cat
0  101   A1
1  256   A2  
2  760   A2
3  888   A3  
...

df2
   A1    A2    A3    ...
0  E50R  AZ33  REZ3 
1  T605  YYU6  YHG5
2  IR50  P0O9  BF53
3  NaN   YY9I  NaN

我想创建一个最终的 DataFrame,如下所示:

df
   101   256   760   888  ...
0  E50R  AZ33  AZ33  REZ3
1  T605  YYU6  YYU6  YHG5
2  IR50  P0O9  P0O9  BF53
3  NaN   YY9I  YY9I  NaN

我尝试了一些带有枢轴的东西,但它似乎没有完成这项工作 你能帮帮我吗?

【问题讨论】:

  • Here 是在 SO 上发布好问题的指南。你应该展示你迄今为止尝试过的东西。
  • 我认为转置其中一张表并加入它们可能会奏效。
  • 我认为 Josh 是对的,但您可能应该从清理数据开始。可能值得一试jstatsoft.org/article/view/v059i10
  • 这已经是一个“最小”的例子了。我应该做些什么来最小化它? “清理数据”是什么意思?

标签: python pandas dataframe join pivot


【解决方案1】:

这比 Wen 的解决方案慢,但我认为概念上更简单:

newdf = df2[df1.cat]
newdf.columns = df1.mag

第一行说“newdf 的第 i 列应该是与df1.cat 的第 i 个元素对应的 df2 的列”。第二行说“newdf的列应该按照df1.mag命名”

【讨论】:

    【解决方案2】:

    您可以使用GroupBynumpy.repeatitertools.chain 的组合:

    from itertools import chain
    
    # map cat to list of mag
    s = df1.groupby('cat')['mag'].apply(list)
    
    # calculate indices for columns, including repeats
    cols_idx = np.repeat(range(len(df2.columns)), s.map(len))
    
    # apply indexing
    res = df2.iloc[:, cols_idx]
    
    # rename columns
    res.columns = list(chain.from_iterable(df2.columns.map(s.get)))
    
    print(res)
    
        101   256   760   888
    0  E50R  AZ33  AZ33  REZ3
    1  T605  YYU6  YYU6  YHG5
    2  IR50  P0O9  P0O9  BF53
    3   NaN  YY9I  YY9I   NaN
    

    性能基准测试

    这里有一些不错的不同解决方案,因此您可能对性能感兴趣。 Wen 的reindex 解决方案显然是赢家。

    %timeit wen(df1, df2)   # 632 µs per loop
    %timeit jpp(df1, df2)   # 2.55 ms per loop
    %timeit scb(df1, df2)   # 7.98 ms per loop
    %timeit abhi(df1, df2)  # 4.52 ms per loop
    

    代码:

    def jpp(df1, df2):
        s = df1.groupby('cat')['mag'].apply(list)
        cols_idx = np.repeat(range(len(df2.columns)), s.map(len))
        res = df2.iloc[:, cols_idx]
        res.columns = list(chain.from_iterable(df2.columns.map(s.get)))    
        return res
    
    def scb(df1, df2):
        df_out = (df2.stack().reset_index()
                     .merge(df1, left_on='level_1', right_on='cat')[['level_0','mag',0]])
        return df_out.pivot('level_0','mag',0).reset_index(drop=True)    
    
    def abhi(df1, df2):
        return df2.T.merge(df1, left_index=True, right_on='cat').drop('cat', axis=1).set_index('mag').T
    
    def wen(df1, df2):
        newdf=df2.reindex(columns=df1.cat)
        newdf.columns=df1.mag
        return newdf
    

    【讨论】:

      【解决方案3】:

      IIUC reindex +re-name

      newdf=df2.reindex(columns=df1.cat)
      newdf.columns=df1.mag
      newdf
      Out[519]: 
      mag   101   256   760   888
      0    E50R  AZ33  AZ33  REZ3
      1    T605  YYU6  YYU6  YHG5
      2    IR50  P0O9  P0O9  BF53
      3     NaN  YY9I  YY9I   NaN
      

      【讨论】:

        【解决方案4】:

        您可以通过转置和合并来完成此操作,然后将列“mag”设置为索引。然后再次转置它。

        df2_transposed = df2.T
        res = df2_transposed.merge(df1,how = "left",left_index=True,right_on='cat')
        del res['cat']
        res.set_index('mag', inplace=True)
        res.T
        
        mag 101      256    760     888
        0   E50R    AZ33    AZ33    REZ3
        1   T605    YYU6    YYU6    YHG5
        2   IR50    P0O9    P0O9    BF53
        3           YY9I    YY9I    
        

        【讨论】:

        • 不错。我也喜欢这个解决方案。仅供参考,如果您愿意 df2.T.merge(df1, left_index=True, right_on='cat').drop('cat', axis=1).set_index('mag').T
        【解决方案5】:

        使用stackmergepivot 的另一种方法:

        df_out = (df2.stack().reset_index()
                     .merge(df1, left_on='level_1', right_on='cat')[['level_0','mag',0]])
        
        df_out.pivot('level_0','mag',0).reset_index(drop=True)
        

        输出:

        mag   101   256   760   888
        0    E50R  AZ33  AZ33  REZ3
        1    T605  YYU6  YYU6  YHG5
        2    IR50  P0O9  P0O9  BF53
        3     NaN  YY9I  YY9I   NaN
        

        【讨论】:

        • 不错的 2-liner +1 :)。但我认为stack 让这变得很慢(我总是想知道为什么他们不能让它更快)。
        • 我同意。您可能可以在那里使用 melt 。
        猜你喜欢
        • 2017-04-08
        • 2020-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-12
        • 2020-12-02
        相关资源
        最近更新 更多