这有点令人费解,但我只会显示我的数据
我构建了以下数据框:
Mid_XYZ Mid_YYY Mid_ZZZ Select1 Select2
867 1019.11 1027.64 1022.68 XYZ YYY
873 1018.04 1027.58 1022.81 XYZ ZZZ
我想通过匹配列名的一部分,从基于 Select1
和 Select2
字符串的列中选择值。在第一行,这将是
1019.11
和 1027.64
(列 Mid_XYZ
和 Mid_YYY
) - 因为 Select1
有字符串 XYZ
而 Select2
有字符串YYY
。
其中,在第二行
1018.04
和 1022.81
(列 Mid_XYZ
和 Mid_ZZZ
)
稍后,我计划将这些值的总和存储在新列中。 DataFrame 看起来像这样
Mid_XYZ Mid_YYY Mid_ZZZ Select1 Select2 Sum
867 1019.11 1027.64 1022.68 XYZ YYY 2046.75
873 1018.04 1027.58 1022.81 XYZ ZZZ 2040.85
我可以将列名更改为精确匹配,但应该有一些正则表达式的解决方案?我知道 df.filter(regex='XYZ')
,但如何按行进行操作?
答案 0 :(得分:5)
使用以下矢量化解决方案:
import numpy as np
# clean rows
clean = df.columns.str.replace('^Mid_', '', regex=True)
# find matching column indices
s1 = np.argmax(clean.values == df['Select1'].values[:, None], axis=1)
s2 = np.argmax(clean.values == df['Select2'].values[:, None], axis=1)
# index and sum
df['Sum'] = df.values[np.arange(len(s1)), s1] + df.values[np.arange(len(s2)), s2]
print(df)
输出
Mid_XYZ Mid_YYY Mid_ZZZ Select1 Select2 Sum
867 1019.11 1027.64 1022.68 XYZ YYY 2046.75
873 1018.04 1027.58 1022.81 XYZ ZZZ 2040.85
答案 1 :(得分:2)
import pandas as pd
如果你有:
df=pd.DataFrame.from_dict({'Mid_XYZ':[1019.11,1018.04],
'Mid_YYY':[1027.64,1027.58],
'Mid_ZZZ':[1022.68,1022.81],
'Select1':['XYZ','XYZ'],
'Select2':['YYY','ZZZ']})
你可以这样做:
df['Sum']=df.apply(lambda row:
row['Mid_'+row['Select1']]+\
row['Mid_'+row['Select2']],
axis=1)
df
将是:
Mid_XYZ Mid_YYY Mid_ZZZ Select1 Select2 Sum
0 1019.11 1027.64 1022.68 XYZ YYY 2046.75
1 1018.04 1027.58 1022.81 XYZ ZZZ 2040.85
如果你不喜欢lambda
函数,可以通过定义一个函数来达到同样的效果:
def sumfunc(row):
return row['Mid_'+row['Select1']]+row['Mid_'+row['Select2']]
那么:
df['Sum']=df.apply(sumfunc,axis=1)
答案 2 :(得分:2)
另一种使用 melt
和 concat
的解决方案:
cols = ['Select1', 'Select2']
df1 = df.melt(id_vars=cols, ignore_index=False)
df['Sum'] = (pd.concat([df1[('Mid_' + df1[col]) == df1['variable']]
for col in cols]).groupby(level=0).sum()) # can also pass `sort=False` to `groupby` for ~10% or something speed boost
df
Out[1]:
Mid_XYZ Mid_YYY Mid_ZZZ Select1 Select2 Sum
867 1019.11 1027.64 1022.68 XYZ YYY 2046.75
873 1018.04 1027.58 1022.81 XYZ ZZZ 2040.85
答案 3 :(得分:2)
除了@Dani Mesejo 的回答之外,我还使用内置在 where 中的 numpy 添加了更快的实现和更直接的...
我的实现是 vec2
:
def vec1(df):
clean = df.columns.str.replace('^Mid_', '', regex=True)
s1 = np.argmax(clean.values == df['Select1'].values[:, None], axis=1)
s2 = np.argmax(clean.values == df['Select2'].values[:, None], axis=1)
# index and sum
df['Sum'] = df.values[np.arange(len(s1)), s1] + df.values[np.arange(len(s2)), s2]
return df
def vec2(df):
clean = df.columns.str.replace('^Mid_', '', regex=True)
idx1 = np.where(clean.values == df['Select1'].values[:,None] )
idx2 = np.where(clean.values == df['Select2'].values[:,None] )
df['Sum'] = df.values[idx1] + df.values[idx2]
return df
这里是时间比较:
我的实现:
%timeit vec2(df) : 388 µs ± 3.97 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
@Dani Mesejo :
%timeit vec1(df) : 405 µs ± 6.42 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)