以交替的列模式(A,-B-A,A-B-A)连接两个 pandas 数据帧(A 和 B)

Concatenate Two pandas Dataframes (A & B) in an Alternating Pattern of Columns (A,-B-A, A-B-A)

我有两个要连接在一起的数据帧。为了清楚起见,我们将这些数据帧称为 A 和 B。我想要做的是以重复的 A-B-A、A-B-A 模式连接每个数据帧的交替列。我的意思是:我希望第一列来自数据帧 A,下一列来自数据帧 B,然后再次来自数据帧 A;那么模式应该重复 A-B-A。

以下是数据帧示例(A 和 B)和预期输出。

data1 = {'ipt_v1': {'V7': 24.588074000000002, 'V4': 22.116738}, 
         'ipt_v2': {'V7': 4.958045, 'V4': 4.726775}}


data2 = {('ipt_v1', 'l'): {'V7': 24.251368038901415, 'V4': 21.806257204224853},
         ('ipt_v1', 'u'): {'V7': 24.92477996109859, 'V4': 22.427218795775136},
         ('ipt_v2', 'l'): {'V7': 4.901618779535504, 'V4': 4.665580151848285},
         ('ipt_v2', 'u'): {'V7': 5.014471220464495, 'V4': 4.787969848151715}}


# expected out
output = {('ipt_v1', 'l'): {'V7': 24.251368038901415, 'V4': 21.806257204224853},
          ('ipt_v1', 'm'): {'V7': 24.588074000000002, 'V4': 22.116738},
          ('ipt_v1', 'u'): {'V7': 24.92477996109859, 'V4': 22.427218795775136},
          ('ipt_v2', 'l'): {'V7': 4.901618779535504, 'V4': 4.665580151848285},
          ('ipt_v2', 'm'): {'V7': 4.958045, 'V4': 4.726775},
          ('ipt_v2', 'u'): {'V7': 5.014471220464495, 'V4': 4.787969848151715}}

此外,我还包含了一个旨在提供预期输出的函数。关于函数我需要一些帮助的部分涉及 # alternating the columns

def combo(data1, data2):
    rws = data1
    ciws = data2
    
    rws.columns = pd.MultiIndex.from_product([['m'],rws.columns])
    rws = rws.swaplevel(0,1, axis=1)
    
    output = pd.concat([ciws, rws], axis=1)
    
    # alternating the columns
    output = (output[list(sum(zip(ciws.columns, rws.columns), ()))])
    return output

# call the function
output = combo(data1, data2)
print(output)

从两个 dfs 中取出列并使用 itertools 交替追加它们,然后在输出 df

中对列重新排序
import itertools
def combo(data1, data2):
    rws = data1
    ciws = data2
    
    rws.columns = pd.MultiIndex.from_product([['m'],rws.columns])
    rws = rws.swaplevel(0,1, axis=1)
    
    output = pd.concat([ciws, rws], axis=1)
    
    # alternating the columns
    rws_cols = list(rws.columns)
    ciws_cols = list(ciws.columns)
    cols =  [x for x in itertools.chain.from_iterable(itertools.zip_longest(ciws_cols,rws_cols)) if x]
    output = output[cols]

    output = (output[list(sum(zip(ciws.columns, rws.columns), ()))])
    return output

# call the function
output = combo(data1, data2)
print(output)

您可以使用insert,它将位置(整数)、名称和值作为参数。在您的情况下,您希望从第 1 列开始的第一个数据帧的每隔三个位置插入列:

import pandas as pd
import numpy as np
data1 = {('ipt_v1', 'm'): {'V7': 24.588074000000002, 'V4': 22.116738}, 
         ('ipt_v2', 'm'): {'V7': 4.958045, 'V4': 4.726775}}


data2 = {('ipt_v1', 'l'): {'V7': 24.251368038901415, 'V4': 21.806257204224853},
         ('ipt_v1', 'u'): {'V7': 24.92477996109859, 'V4': 22.427218795775136},
         ('ipt_v2', 'l'): {'V7': 4.901618779535504, 'V4': 4.665580151848285},
         ('ipt_v2', 'u'): {'V7': 5.014471220464495, 'V4': 4.787969848151715}}

df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)

df = df2.copy()
i = 1
for c in df1.columns:
    df.insert(i, c, df1[c])
    i += 3

在您的情况下,您也可以使用简单的排序获得相同的结果:

df = pd.concat([df1, df2], axis=1)
sorted_columns = sorted(df.columns)
df = df[sorted_columns]

一个简单的方法是考虑您期望的模式。

你想要A-B-A-A-B-A。因此,如果您 concat df2df1,并假设列索引 [0, 1, 2, 3, *4, *5]* 表示 df1 项),您想要重新排序 [0, *4, 1, 2, *5, 3].

为此,您可以这样做:

import numpy as np

n = len(df2) # 4
m = len(df1) # 2

a = np.arange(n+m)
# array([0, 1, 2, 3, 4, 5])

a = np.r_[np.delete(a, a[1::3]), a[1::3]]
# order in which to take values
# move 1, 4 to the end or the array
# array([0, 2, 3, 5, 1, 4])

np.argsort(a)
# sorted order
# array([0, 4, 1, 2, 5, 3])

现在,您只需执行:

output = pd.concat([ciws, rws], axis=1)
output.iloc[:, np.argsort(a)]

你在这里:

       ipt_v1                          ipt_v2                    
            l          m          u         l         m         u
V7  24.251368  24.588074  24.924780  4.901619  4.958045  5.014471
V4  21.806257  22.116738  22.427219  4.665580  4.726775  4.787970

更简单的例子:

df1 = pd.DataFrame(list('BB'), range(4,6)).T
#    4  5
# 0  B  B

df2 = pd.DataFrame(list('AAAA'), range(4)).T
#    0  1  2  3
# 0  A  A  A  A

df3 = pd.concat([df2, df1], axis=1).iloc[:, np.argsort(a)]
#    0  4  1  2  5  3
# 0  A  B  A  A  B  A