根据部分匹配的列名插入多列
insert multiple columns based on column name with partial match
我认为这里会有一个简单的解决方案,但我遗漏了一些东西...
我有两个数据框。一份原件,另一份带有一些处理过的数据。第二个数据框中的列名部分匹配第一个数据框中的列。有多个列名部分匹配。第二个数据框中的多个列需要重新插入到原始数据框中具有单个部分匹配列名称的相同位置(因此数据框的大小自然会增加)。下面复制了数据示例和预期输出。它必须是 'programmatic' 因为我有很多 columns/instances.
任何评论对我都非常有帮助。
非常感谢!
原始数据
df1 = {'id': ['1','2','3','4'],
'ab': ['1', '2', '3', '4'],
'xy': ['1', '2', '3','4'],
'cd': ['1', '2', '3','4'],
'ef':['1', '2', '3', '4'],
'lm':['1', '2', '3', '4'],
'fa':['1', '2', '3', '4'] }
df1 = pd.DataFrame(df1, columns = ['id','ab', 'xy', 'cd', 'ef', 'lm', 'fa'])
已处理数据
df2 = {'id': ['1','2','3','4'],
'ab? op': ['green', 'red', 'blue', 'None'],
'ab? 1': ['red', 'yellow', 'None', 'None'],
'cd': ['L', 'XL', 'M','L'],
'efab? cba' : ['husband', 'wife', 'husband', 'None'],
'efab? 1':['son', 'grandparent', 'son', 'None'],
'efab? 2':['None', 'son', 'None', 'None'],
'fab? 4':['9', '10', '5', '3'],
'fab? po':['England', 'Scotland', 'Wales', 'NA'] }
df2 = pd.DataFrame(df2, columns = ['id','ab? op', 'ab? 1', 'cd', 'efab? cba', 'efab? 1', 'efab? 2', 'fab? 4', 'fab? po'])
预期输出
e = {'id': ['1','2','3','4'],
'ab? op': ['green', 'red', 'blue', 'None'],
'ab? 1': ['red', 'yellow', 'None', 'None'],
'xy': ['1', '2', '3','4'],
'cd': ['L', 'XL', 'M','L'],
'lm':['1', '2', '3', '4'],
'efab? cba' : ['husband', 'wife', 'husband', 'None'],
'efab? 1':['son', 'grandparent', 'son', 'None'],
'efab? 2':['None', 'son', 'None', 'None'],
'fab? 4':['9', '10', '5', '3'],
'fab? po':['England', 'Scotland', 'Wales', 'NA'] }
expected = pd.DataFrame(e, columns = ['id','ab? op', 'ab? 1', 'xy', 'cd', 'lm', 'efab? cba', 'efab? 1', 'efab? 2', 'fab? 4', 'fab? po'])
将两个差异与修改后的列名称
结合后 argsort
c2 = df2.columns.str[:2]
c1 = df1.columns
x = pd.concat([df2,df1[c1[~c1.isin(c2)]]],axis=1)
x = x.iloc[:,x.columns.str[:2].map(dict(zip(c1,range(len(c1))))).argsort()]
x
Out[115]:
id ab? op ab? 1 xy cd efab? cba efab? 1 efab? 2 lm fab? 4 fab? po
0 1 green red 1 L husband son None 1 9 England
1 2 red yellow 2 XL wife grandparent son 2 10 Scotland
2 3 blue None 3 M husband son None 3 5 Wales
3 4 None None 4 L None None None 4 3 NA
如果Python 3.8+,那么
result = pd.concat([df1[col]
if (candidate := df2.loc[:, df2.columns.str.startswith(col)]).empty
else candidate
for col in df1],
axis=1)
对于 df1
的每一列,我们在 df2
中查找 startswith
列名称在 df1
中的 candidate
列。如果存在这样的列,则将候选人放入结果中,否则将该列保留在 df1
.
中
获得
id ab? op ab? 1 xy cd efab? cba efab? 1 efab? 2 lm fab? 4 fab? po
0 1 green red 1 L husband son None 1 9 England
1 2 red yellow 2 XL wife grandparent son 2 10 Scotland
2 3 blue None 3 M husband son None 3 5 Wales
3 4 None None 4 L None None None 4 3 NA
如果 3.8-,
cols = []
for col in df1:
candidate = df2.loc[:, df2.columns.str.startswith(col)]
cols.append(df1[col] if candidate.empty else candidate)
result = pd.concat(cols, axis=1)
我认为这里会有一个简单的解决方案,但我遗漏了一些东西...
我有两个数据框。一份原件,另一份带有一些处理过的数据。第二个数据框中的列名部分匹配第一个数据框中的列。有多个列名部分匹配。第二个数据框中的多个列需要重新插入到原始数据框中具有单个部分匹配列名称的相同位置(因此数据框的大小自然会增加)。下面复制了数据示例和预期输出。它必须是 'programmatic' 因为我有很多 columns/instances.
任何评论对我都非常有帮助。
非常感谢!
原始数据
df1 = {'id': ['1','2','3','4'],
'ab': ['1', '2', '3', '4'],
'xy': ['1', '2', '3','4'],
'cd': ['1', '2', '3','4'],
'ef':['1', '2', '3', '4'],
'lm':['1', '2', '3', '4'],
'fa':['1', '2', '3', '4'] }
df1 = pd.DataFrame(df1, columns = ['id','ab', 'xy', 'cd', 'ef', 'lm', 'fa'])
已处理数据
df2 = {'id': ['1','2','3','4'],
'ab? op': ['green', 'red', 'blue', 'None'],
'ab? 1': ['red', 'yellow', 'None', 'None'],
'cd': ['L', 'XL', 'M','L'],
'efab? cba' : ['husband', 'wife', 'husband', 'None'],
'efab? 1':['son', 'grandparent', 'son', 'None'],
'efab? 2':['None', 'son', 'None', 'None'],
'fab? 4':['9', '10', '5', '3'],
'fab? po':['England', 'Scotland', 'Wales', 'NA'] }
df2 = pd.DataFrame(df2, columns = ['id','ab? op', 'ab? 1', 'cd', 'efab? cba', 'efab? 1', 'efab? 2', 'fab? 4', 'fab? po'])
预期输出
e = {'id': ['1','2','3','4'],
'ab? op': ['green', 'red', 'blue', 'None'],
'ab? 1': ['red', 'yellow', 'None', 'None'],
'xy': ['1', '2', '3','4'],
'cd': ['L', 'XL', 'M','L'],
'lm':['1', '2', '3', '4'],
'efab? cba' : ['husband', 'wife', 'husband', 'None'],
'efab? 1':['son', 'grandparent', 'son', 'None'],
'efab? 2':['None', 'son', 'None', 'None'],
'fab? 4':['9', '10', '5', '3'],
'fab? po':['England', 'Scotland', 'Wales', 'NA'] }
expected = pd.DataFrame(e, columns = ['id','ab? op', 'ab? 1', 'xy', 'cd', 'lm', 'efab? cba', 'efab? 1', 'efab? 2', 'fab? 4', 'fab? po'])
将两个差异与修改后的列名称
结合后argsort
c2 = df2.columns.str[:2]
c1 = df1.columns
x = pd.concat([df2,df1[c1[~c1.isin(c2)]]],axis=1)
x = x.iloc[:,x.columns.str[:2].map(dict(zip(c1,range(len(c1))))).argsort()]
x
Out[115]:
id ab? op ab? 1 xy cd efab? cba efab? 1 efab? 2 lm fab? 4 fab? po
0 1 green red 1 L husband son None 1 9 England
1 2 red yellow 2 XL wife grandparent son 2 10 Scotland
2 3 blue None 3 M husband son None 3 5 Wales
3 4 None None 4 L None None None 4 3 NA
如果Python 3.8+,那么
result = pd.concat([df1[col]
if (candidate := df2.loc[:, df2.columns.str.startswith(col)]).empty
else candidate
for col in df1],
axis=1)
对于 df1
的每一列,我们在 df2
中查找 startswith
列名称在 df1
中的 candidate
列。如果存在这样的列,则将候选人放入结果中,否则将该列保留在 df1
.
获得
id ab? op ab? 1 xy cd efab? cba efab? 1 efab? 2 lm fab? 4 fab? po
0 1 green red 1 L husband son None 1 9 England
1 2 red yellow 2 XL wife grandparent son 2 10 Scotland
2 3 blue None 3 M husband son None 3 5 Wales
3 4 None None 4 L None None None 4 3 NA
如果 3.8-,
cols = []
for col in df1:
candidate = df2.loc[:, df2.columns.str.startswith(col)]
cols.append(df1[col] if candidate.empty else candidate)
result = pd.concat(cols, axis=1)