我有一个数据框,如下所示:
Index X_1 X_2 X_3 W_1 W_2 W_3
1 IEZ XOP ABC 0.42 0.18 0.40
2 PXJ ABC XES 0.47 0.12 0.41
3 ABC RYE PXE 0.23 0.33 0.44
4 XOP IEZ ABC 0.62 0.20 0.18
我想遍历X_1至X_3列之间“ ABC”的每个实例的每个索引行。对于每个实例,我想从W_1到W_3列中提取相应的值,并将其附加到新的W列中。
例如,对于索引行1,如果X_3中出现ABC实例,它将从W_3中提取相应的值。
最终产品应如下所示。
Index X_1 X_2 X_3 W_1 W_2 W_3 **W**
1 IEZ XOP ABC 0.42 0.18 0.40 **0.40**
2 PXJ ABC XES 0.47 0.12 0.41 **0.12**
3 ABC RYE PXE 0.23 0.33 0.44 **0.23**
4 XOP IEZ ABC 0.62 0.20 0.18 **0.18**
如何仅对导入的numpy和pandas模块执行此操作?
答案 0 :(得分:0)
有趣。我相信有更好的方法,但是:
x_cols = [x for x in df.columns if x.startswith('X_')]
res_dfs = []
for col in x_cols:
idx = col.split("_")[1]
xw = df[col, "W_{idx}]
xw = xw.loc[xw[col] == 'ABC']
xw = xw[[f"W_{idx}"]].rename(columns={f"W_{idx}": 'W'})
res = df.join(xw).dropna()
res_dfs.append(res)
df = pd.concat(res_dfs)
基本上,我遍历x col及其匹配的w col,找到x值是'abc'的位置,并用匹配的w值填充新的'w'列。
这是从我的手机上来的,所以我无法尝试,但这是一般的想法。
答案 1 :(得分:0)
import numpy as np
import pandas as pd
# df is your dataframe
# idxs = np.argwhere(df.values == "ABC") will also work
# if "ABC" only appears once per row.
idxs = np.argwhere(df.values[:, :3] == "ABC")
idxs[:, 1] += 3
w = df.values[idxs[:, 0], idxs[:, 1]]
df = df.assign(W=w)
或
matches = df.iloc[:, :3] == "ABC"
w = df.iloc[:, 3:].values[matches]
df = df.assign(W=w)
答案 2 :(得分:0)
另一种方法:
df = pd.DataFrame({'X_1' : ['IEZ', 'PXJ', 'ABC', 'XOP'],
'X_2' : ['XOP', 'ABC', 'RYE', 'IEZ'],
'X_3' : ['ABC', 'XES','PXE', 'ABC'],
'W_1' : [0.42, 0.47, 0.23, 0.62],
'W_2' : [0.18, 0.12, 0.33, 0.20],
'W_3' : [0.40, 0.41, 0.44, 0.18]})
首先,取数字列:
num_columns = df.loc[:,'W_1':'W_3']
接下来,使用X_1
-> X_3
列生成布尔掩码:
df_mask = (df.loc[:,'X_1':'X_3']=='ABC').values
最后,使用DataFrame mask方法,当单元格为True时将返回NaN,而当掩码为False时将返回单元格值。然后,我们将对结果行求和,并将其分配给原始DataFrame:
df['W'] = num_columns.mask(~df_mask).sum(axis=1)
当然可以将其合并为一行:
df['W'] = (df.loc[:,'W_1':'W_3']
.mask(~(df.loc[:,'X_1':'X_3']=='ABC').values)
.sum(axis=1))
编辑:
当然,这仅在每行只有'ABC'
个实例的情况下才有效-您可能需要对此进行检查。
答案 3 :(得分:0)
将pd.DataFrame.where
与布尔索引一起使用:
df1, df2 = df[[c for c in df if c[0]=='X']], df[[c for c in df if c[0]=='W']]
df["W"] = df2.where((df1 == 'ABC').values).sum(1)
print(df)
Index X_1 X_2 X_3 W_1 W_2 W_3 W
0 1 IEZ XOP ABC 0.42 0.18 0.40 0.40
1 2 PXJ ABC XES 0.47 0.12 0.41 0.12
2 3 ABC RYE PXE 0.23 0.33 0.44 0.23
3 4 XOP IEZ ABC 0.62 0.20 0.18 0.18
这是基于df1
和df2
始终具有相同形状的假设进行的。