我正在尝试在Pandas中创建一个新列。我有一个现有的文本列,并且我希望这个新列包含另一个列中包含的值,其中行值与列名部分匹配。它类似于该线程,但就我而言,我只会部分匹配:
Python: pandas: match row value to column name/ key's value
我的桌子就像这样
Field UKA_rf4 UKB UKDdsdf
UKA 1 4 54
UKB 2 5 7787
UKD 97 54 765656
我想要的样子是:
Field UKA_rf4 UKB UKDdsdf Value
UKA 1 4 54 1
UKB 2 5 7787 5
UKD 97 54 765656 765656
第一行的结果为1,因为列名'UKA_rf4'中包含'UKA'
第二行与列名完全匹配,第三列是部分匹配。
有什么建议吗?
答案 0 :(得分:2)
如果列之间总是匹配,并且Field
的每个值都使用DataFrame.lookup
:
s = df['Field']
a = df.columns.str.extract('(' + '|'.join(s) + ')', expand=False)
df['Value'] = df.set_axis(a, axis=1,inplace=False).lookup(df.index, s)
print (df)
Field UKA_rf4 UKB UKDdsdf Value
0 UKA 1 4 54 1
1 UKB 2 5 7787 5
2 UKD 97 54 765656 765656
类似的解决方案:
df = df.set_index('Field')
a = df.columns.str.extract('(' + '|'.join(s) + ')', expand=False)
df['Value'] = df.set_axis(a, axis=1,inplace=False).lookup(df.index, df.index)
但是lookup
的问题是是否缺少某些值,因此这里是DataFrame.melt
进行整形的替代方法,按Series.str.extract
提取具有Field
列和{ {3}}:
df1 = df.melt('Field', var_name='var')
df1['cols'] = df1['var'].str.extract('(' + '|'.join(df['Field']) + ')', expand=False)
s = df1[df1['Field'] == df1['cols']].drop_duplicates('Field').set_index('Field')['value']
df['Value'] = df['Field'].map(s)
print (df)
Field UKA_rf4 UKB UKdsdf Value
0 UKA 1 4 54 1.0
1 UKB1 2 5 7787 NaN
2 UKD 97 54 765656 NaN
答案 1 :(得分:1)
您可以使用列表理解
df = pd.DataFrame({'Fields':['UKA','UKB','UKD'],'UKA_rf4':[1,2,97],'UKB':[4,5,54],'UKDdsdf':[54,7787,765656]})
df = df.set_index('Fields')
df['Values'] = [df[j][index] for index,i in enumerate(df.index) for j in df.columns if i in j]
print(df)
UKA_rf4 UKB UKDdsdf Values
Fields
UKA 1 4 54 1
UKB 2 5 7787 5
UKD 97 54 765656 765656
答案 2 :(得分:1)
我们仍然可以通过在此处清除列名来使用lookup
:
df2 = df.copy()
df2.columns = ['Field'] + [col[:3] for col in df2.iloc[:, 1:].columns]
df['Value'] = df2.lookup(df2.index, df2['Field'])
Field UKA_rf4 UKB UKDdsdf Value
0 UKA 1 4 54 1
1 UKB 2 5 7787 5
2 UKD 97 54 765656 765656