使用列名前缀将每列乘以它们的相对因子

2024-06-28 22:06:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个矩阵

id |v1_m1 v2_m1 v3_m1 f_m1 v1_m2 v2_m2 v3_m2 f_m2| 
1  |  0     .5    .5    4   0.1   0.3    0.6   4 |
2  |  0.3   .3    .4    8   0.2   0.4    0.4   7 |

我想要的是将m1中的每个v乘以f_m1列,并将所有带后缀“_m2”的v列乘以ghe f_m2列

我期望的输出如下:

id |v1_m1 v2_m1 v3_m1 v1_m2 v2_m2 v3_m2 | 
1  |  0    2      2    0.4   1.2   2.4  |
2  | 2.4  2.4    3.2   1.4   2.8   2.8  |

Tags: id矩阵v3后缀v2v1m1m2
3条回答

您可以通过一些奇特的数据帧重塑来实现这一点:

df.columns = pd.MultiIndex.from_arrays(zip(*df.columns.str.split('_')))
df=df.stack()
df_mul = df.filter(like='v').mul(df.filter(like='f').squeeze(), axis=0)
df_mul = df_mul.unstack().sort_index(level=1, axis=1)
df_mul.columns = [f'{i}_{j}' for i, j in df_mul.columns]
df_mul

输出:

    v1_m1  v2_m1  v3_m1  v1_m2  v2_m2  v3_m2
id                                          
1     0.0    2.0    2.0    0.4    1.2    2.4
2     2.4    2.4    3.2    1.4    2.8    2.8

详情:

  • 在“\u1”上创建多索引列标题split
  • 重塑数据帧stack,将m#改为行,留下四列f和 三个v
  • 使用filter,我们可以通过f选择v列和multiply 通过选择单个列并使用squeeze来创建序列 从单列数据帧创建pd.Series
  • unstack将m#级别返回到列
  • 使用将多索引列标题展平到单个级别 具有列表理解的f字符串
for m in range (1,maxm):
    for i in range (1,maxv):
        df["v{}_m{}".format(i,m)] = df["v{}_m{}".format(i,m)]*df["f_m{}".format(m)]
for m in range (1,maxm):
    df.drop(columns=["f_m{}".format(m)])

假设您的矩阵是一个名为df的数据框架,如果您喜欢,我想推荐一种列表理解方法

import itertools

items = [(i[0][0],i[0][1].multiply(i[1][1]))
         for i in itertools.product(df.items(),repeat=2) 
         if (i[0][0][-2:]==i[1][0][-2:]) 
         and i[1][0][:1]=='f' 
         and i[0][0][:1]!='f']

df_mul = pd.DataFrame.from_dict({i[0]:i[1] for i in items})

对于这个问题的更大版本,它应该是最快的

解释-

  1. 为每列之间的叉积创建一个生成器,作为(c1,c2)元组
  2. 仅保留c1、c2和c2最后两个字母以“f”开头的列,而c1不以“f”开头(留下要作为单个元组操作的列)。类似这样的-[('v1_m1', 'f_m1'), ('v2_m1', 'f_m1'), ('v1_m2', 'f_m2')]
  3. 将列相乘,附加一个列名并将其保存为项(类似于df.items()的结构)
  4. 将项目转换为数据帧

相关问题 更多 >