2016-05-12 4 views
1

Если у меня есть кадр данных с переменными A, B, C, D, E, как я могу создать цикл for или while для создания переменных, выполнив все возможные комбинации существующие переменные, использующие все переменные и все возможные математические операторы (+, -, /, *)?Python Создание новых столбцов/атрибутов для всех возможных комбинаций переменных

Для перехода из данных рамы со следующими переменными:

ABCDE

к одному, как это:

ABCDE А + В А + С А + D A + EA * B ...

ответ

2

Решение

Вы хотите использовать numpy

import numpy as np 

vars = [1, 2, 3] 

np.concatenate([ 
     np.add.outer(vars, vars), 
     np.subtract.outer(vars, vars), 
     np.multiply.outer(vars, vars), 
     np.divide.outer(vars, vars)]).flatten() 

Похоже:

array([ 2, 3, 4, 3, 4, 5, 4, 5, 6, 0, -1, -2, 1, 0, -1, 2, 1, 
     0, 1, 2, 3, 2, 4, 6, 3, 6, 9, 1, 0, 0, 2, 1, 0, 3, 
     1, 1]) 

Объяснение

# All possible additions 
print np.add.outer(vars, vars) 

# All possible subtractions 
print np.subtract.outer(vars, vars) 

# All possible multiplications 
print np.multiply.outer(vars, vars) 

# All possible divisions 
print np.divide.outer(vars, vars) 

выглядит так:

[[2 3 4] 
[3 4 5] 
[4 5 6]] 

[[ 0 -1 -2] 
[ 1 0 -1] 
[ 2 1 0]] 

[[1 2 3] 
[2 4 6] 
[3 6 9]] 

[[1 0 0] 
[2 1 0] 
[3 1 1]] 
2

Вы можете использовать product и eval оценить все возможные комби нации. Они сохраняются с использованием понимания словаря, а затем объединены с исходными данными.

from itertools import product 

df = pd.DataFrame({'A': [1, 2], 'B': [3, 4], 'C': [5, 6]}) 

transformations = {"".join(p): eval("df.loc[:, '{0}'] {1} df.loc[:, '{2}']".format(*p)) 
        for p in product(df, list('+-/*'), df)} 
transformations = pd.concat([df, pd.DataFrame(transformations)], axis=1) 

>>> transformations 
    A B C A+A A+B A+C A-A A-B A-C A/A ... C+C C-A C-B C-C C/A C/B C/C C*A C*B C*C 
0 1 3 5 2 4 6 0 -2 -4 1 ... 10 4 2 0 5 2 1 5 15 25 
1 2 4 6 4 6 8 0 -2 -4 1 ... 12 4 2 0 3 2 1 12 24 36 

[2 rows x 39 columns] 
+0

Использование 'eval' не рекомендуется – bluesmonk

0

Петли - не самый эффективный способ достижения этого. Тем не менее, я полагаю, что в этом случае есть смысл/необходимость в их использовании.

Итак, предположим, что вы сказали, что хотите провести элементарную операцию, используя только итерации (циклы) и никакие сторонние библиотеки. Мы можем сделать это эффективно (или как можно более эффективно) с помощью генераторов. Это, как я бы об этом:

data = [1, 2, 3, 4, 5] 

operations = { 
    "+": lambda x,y: (value+y for value in x), 
    "-": lambda x,y: (value-y for value in x), 
    "*": lambda x,y: (value*y for value in x), 
    "/": lambda x,y: (value/y for value in x), 
} 

calculations = (
    (key, val, oper(data, val)) 
    for key, oper in sorted(operations.items()) 
    for val in data 
) 

Теперь давайте показывать результаты:

for item in calculations: 
    op, val, res = item 
    preped_res = str.join(
     ' | ', ["{:^6.2g}".format(val) for val in res] 
    ) 

    print(" {} {} {:.2g} = | {} |".format(data, op, val, preped_res)) 

, который будет выглядеть так:

[1, 2, 3, 4, 5] * 1 = | 1 | 2 | 3 | 4 | 5 | 
[1, 2, 3, 4, 5] * 2 = | 2 | 4 | 6 | 8 | 10 | 
[1, 2, 3, 4, 5] * 3 = | 3 | 6 | 9 | 12 | 15 | 
[1, 2, 3, 4, 5] * 4 = | 4 | 8 | 12 | 16 | 20 | 
[1, 2, 3, 4, 5] * 5 = | 5 | 10 | 15 | 20 | 25 | 
[1, 2, 3, 4, 5] + 1 = | 2 | 3 | 4 | 5 | 6 | 
[1, 2, 3, 4, 5] + 2 = | 3 | 4 | 5 | 6 | 7 | 
[1, 2, 3, 4, 5] + 3 = | 4 | 5 | 6 | 7 | 8 | 
[1, 2, 3, 4, 5] + 4 = | 5 | 6 | 7 | 8 | 9 | 
[1, 2, 3, 4, 5] + 5 = | 6 | 7 | 8 | 9 | 10 | 
[1, 2, 3, 4, 5] - 1 = | 0 | 1 | 2 | 3 | 4 | 
[1, 2, 3, 4, 5] - 2 = | -1 | 0 | 1 | 2 | 3 | 
[1, 2, 3, 4, 5] - 3 = | -2 | -1 | 0 | 1 | 2 | 
[1, 2, 3, 4, 5] - 4 = | -3 | -2 | -1 | 0 | 1 | 
[1, 2, 3, 4, 5] - 5 = | -4 | -3 | -2 | -1 | 0 | 
[1, 2, 3, 4, 5]/1 = | 1 | 2 | 3 | 4 | 5 | 
[1, 2, 3, 4, 5]/2 = | 0.5 | 1 | 1.5 | 2 | 2.5 | 
[1, 2, 3, 4, 5]/3 = | 0.33 | 0.67 | 1 | 1.3 | 1.7 | 
[1, 2, 3, 4, 5]/4 = | 0.25 | 0.5 | 0.75 | 1 | 1.2 | 
[1, 2, 3, 4, 5]/5 = | 0.2 | 0.4 | 0.6 | 0.8 | 1 | 

Надеется, что это отвечает на ваш вопрос. Но если есть что-то, что я пропустил, пожалуйста, не стесняйтесь говорить мне, и мы увидим, что мы можем сделать.

0

Если я понял вашу проблему права, reindex и itertools ваши друзья

In [21]: import pandas as pd 

In [22]: import numpy as np 

In [23]: df = pd.DataFrame({'a':np.arange(5), 'b':np.arange(5), 'c':np.arange(5) 
    ...: }) 

In [24]: df 
Out[24]: 
    a b c 
0 0 0 0 
1 1 1 1 
2 2 2 2 
3 3 3 3 
4 4 4 4 

In [26]: operations = ['*', '/', '-', '+'] 

In [30]: new_columns = list(''.join([a,b,c]) for a,b,c in itertools.product(s1,s2,s1) if a!=c) # joins the permutations of the three elements, and returns those where the first is not repeated i.e. a*a, b-b, etc. You can remove the last if to get all of them 

In [31]: new_columns 
Out[31]: 
['a*b', 
'a*c', 
'a/b', 
'a/c', 
'a-b', 
'a-c', 
'b*a', 
'b*c', 
'b/a', 
'b/c', 
'b-a', 
'b-c', 
'c*a', 
'c*b', 
'c/a', 
'c/b', 
'c-a', 
'c-b'] 

In [33]: df.reindex(columns=[*df.columns, *new_columns], fill_value=np.nan) # rewrites the df using by unpacking the existing columns, and also the new columns. Fill the new empty places with `NaN`. 
Out[33]: 
    a b c a*b a*c a/b a/c a-b a-c b*a ... b/a b/c b-a b-c c*a \ 
0 0 0 0 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN 
1 1 1 1 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN 
2 2 2 2 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN 
3 3 3 3 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN 
4 4 4 4 NaN NaN NaN NaN NaN NaN NaN ... NaN NaN NaN NaN NaN 

    c*b c/a c/b c-a c-b 
0 NaN NaN NaN NaN NaN 
1 NaN NaN NaN NaN NaN 
2 NaN NaN NaN NaN NaN 
3 NaN NaN NaN NaN NaN 
4 NaN NaN NaN NaN NaN 

Вы можете изменить функцию ''.join() любым вы хотите, и получить тот же результат.

Смежные вопросы