以交替的列模式(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
df2
和 df1
,并假设列索引 [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
我有两个要连接在一起的数据帧。为了清楚起见,我们将这些数据帧称为 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
df2
和 df1
,并假设列索引 [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