itertools:获取操作( + - * / )和列的组合

Posted

技术标签:

【中文标题】itertools:获取操作( + - * / )和列的组合【英文标题】:itertools: Getting combinations of operations ( + - * / ) and columns 【发布时间】:2020-07-11 09:43:40 【问题描述】:

给定一个数值数据框,我想对所有列组合执行加、减、乘和除。

对于 3 及以上的组合,最快的方法是什么?

下面给出了一个最小的可重现示例,其中包含 2 的组合。

import numpy as np
import pandas as pd
from itertools import combinations
from itertools import permutations
from sklearn.datasets import load_boston 

# the dataset
X, y = load_boston(return_X_y=True)
X = pd.DataFrame(X)

combos2 = list(combinations(X.columns,2))
perm3 = list(permutations(X.columns,3))  # how would i do this with out typing out all the permutations
for i in combos2:
    X[f'i[0]_X_i[1]'] = X.iloc[:,i[0]]*X.iloc[:,i[1]]  # Multiply
    X[f'i[0]_+_i[1]'] = X.iloc[:,i[0]]+X.iloc[:,i[1]]  # Add
    X[f'i[0]_-_i[1]'] = X.iloc[:,i[0]]-X.iloc[:,i[1]]  # Subtract
    X[f'i[0]_/_i[1]'] = X.iloc[:,i[0]]/(X.iloc[:,i[1]]+1e-20)   # Divide

我正在考虑一种将“运算符 + * - /”添加到组合中的方法,这样可以用比手动输入所有组合更少的行来编写它,但我不知道从哪里开始?

我想要所有订单:即 (a * b + c) 、 (a * b - c) 、 (a * b / c) 等

最好不要留下重复的列。即 (a + b + c) 和 (c + b + a)

例如,如果我有 3 列 a b c。我想要一个新列 (a * b + c)。

【问题讨论】:

3 的组合:您是只寻找 a+b+c(三列相同的运算符)还是 a*b+c(三列不同的运算符)?如果是后者,那么优先顺序呢? (优先级问题也适用于 a / b / c)。 我想要三列上的不同运算符以及相同的运算符组合。也是优先顺序的所有组合。如果我不清楚,我很抱歉。我会尝试改写它。我的问题的措辞应该说产品而不是组合吗? 【参考方案1】:

我希望这会帮助您入门:

operators = ['-', '+', '*', '/']
operands = ['a', 'b', 'c']

# find out all possible combination of operators first. So if you have 3 operands, that would be all permutations of the operators, taken 2 at a time. Also append the same expression operator combinations to the list

from itertools import permutations
operator_combinations = list(permutations(operators, len(operands)-1))
operator_combinations.extend([op]*(len(operands)-1) for op in operators)

# create a list for each possible expression, appending it with an operand and then an operator and so on, finishing off with an operand.

exp = []
for symbols in operator_combinations:
    temp = []
    for o,s in zip(operands, symbols):
        temp.extend([o,s])
    temp.append(operands[-1])
    exp.append(temp)

for ans in exp:
    print(''.join(ans))

输出:

a-b+c
a-b*c
a-b/c
a+b-c
a+b*c
a+b/c
a*b-c
a*b+c
a*b/c
a/b-c
a/b+c
a/b*c
a-b-c
a+b+c
a*b*c
a/b/c

【讨论】:

如果我理解正确,我必须在输出中使用 eval(),但我很难弄清楚这个解决方案如何扩展到我的示例中的数据集集。 你好@HarriS,我不知道你在处理什么数据集。我已经编写了一个代码,用于使用给定的操作数和运算符生成所有可能的表达式,这就是我认为你想要做的。 例如,如果我在 DataFrame a b c 中有 3 列。我想要一个新列,它是您解决方案中所有打印输出的评估。所以(如果原始数据集有 3 列,则为 16 个新列)。我在示例中使用了默认的 sklearn 波士顿数据集。【参考方案2】:

这是一个简单的解决方案,它输出所有列的 2 和 3 的组合。

    组合列表 使用操作符包制作函数 for 循环组合 这可能有重复的列,因此会删除重复的列
from sklearn.datasets import load_boston 
from itertools import combinations
import operator as op 

X, y = load_boston(return_X_y=True)
X =  pd.DataFrame(X)

comb= list(combinations(X.columns,3))

def operations(x,a,b):
   if (x == '+'): 
      d =  op.add(a,b) 
   if (x == '-'): 
      d =  op.sub(a,b) 
   if (x == '*'): 
      d =  op.mul(a,b)     
   if (x == '/'): # divide by 0 error
      d =  op.truediv(a,(b + 1e-20)) 
   return d


for x in ['*','/','+','-']:
  for y in ['*','/','+','-']:
    for i in comb:
      a = X.iloc[:,i[0]].values
      b = X.iloc[:,i[1]].values
      c = X.iloc[:,i[2]].values
      d = operations(x,a,b)
      e = operations(y,d,c)
      X[f'i[0]xi[1]yi[2]'] = e
      X[f'i[0]xi[1]'] = d

X = X.loc[:,~X.columns.duplicated()]

【讨论】:

以上是关于itertools:获取操作( + - * / )和列的组合的主要内容,如果未能解决你的问题,请参考以下文章

Python itertools 操作迭代对象

Python / Itertools:按名称获取最新文件

Python:获取 itertools.combinations 以返回逐渐变大的组合

itertools模块

itertools

itertools模块