Pythonにおける置換


Cover Credit

概要

Itertools は、効率的なループ処理のための反復子を作成するための高速、メモリ効率の良いツールのコアセットですdocumentation ここに.

反復ツール置換


多くの用途itertools を作成するpermutations() リスト内の項目のすべての組み合わせを返す機能.
私は異なった段階でユーザーfunnelsを巻き込んだプロジェクトに取り組んでいました、そして、我々はユーザーがどれくらいの異なる「パス」をとることができるかについて疑問に思っていました.

漏斗
我々の仮説の例では、我々は合計6つの順列のために3つのステージで漏斗を見ています.以下は公式です

あなたが販売/マーケティングfunnelを使用しているならば、あなたはあなたの漏斗がすべての可能な経路を望まないかもしれないように、あなたの漏斗がどのように見えるかに注意しなければなりません、しかし、潜在的に見落とされた経路を調査することに興味があるならば、読んでください.
これがPythondocumentation for itertools , and permutations 具体的には我々はよりよくこの機能で何が起こっているかを理解するためにコードを壊します.
注:私は事実の後、より明確な選択肢を見つけました.つのバージョンを比較する際に値がありますが、以下の最後のセクションにスキップしてください.
我々は、で始まるiterablelist を指定します.The permutations 関数は2つのパラメータをとるiterable and r リストからの項目の数は、私たちが結合を見つけることに興味があることです.リスト内の3つの項目がある場合は、一般的に3つの項目のすべての組み合わせを見つけることができます.
以下はコードとそれ以降の故障です
# list of length 3
list1 = ['stage 1', 'stage 2', 'stage 3']

# iterable is the list
# r = number of items from the list to find combinations of


def permutations(iterable, r=None):
    """Find all possible order of a list of elements"""
    # permutations('ABCD',2)--> AB AC AD BA BC BD CA CB CD DA DB DC
    # permutations(range(3))--> 012 021 102 120 201 210
    # permutations(list1, 6)--> ...720 permutations
    pool = tuple(iterable)
    n = len(pool)
    r = n if r is None else r
    if r > n:
        return
    indices = list(range(n))                     # [0, 1, 2]
    cycles = list(range(n, n-r, -1))             # [3, 2, 1]
    yield tuple(pool[i] for i in indices[:r])
    while n:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i+1:] + indices[i:i+1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                yield tuple(pool[i] for i in indices[:r])
                break
        else:
            return


#permutations(list1, 6)

perm = permutations(list1, 3)
count = 0

for p in perm:
    count += 1
    print(p)
print("there are:", count, "permutations.")

我々がする最初のことはiterable 入力パラメータはlisttuple .
pool = tuple(iterable)
これを行う理由はいくつかあります.最初にtuples より速いlists ; the permutations() 関数は入力にいくつかの操作を行い、tuple より高速な操作を許可しますtuples 変更不能で、リストを変更する恐れがなければ、異なる操作の束を行うことができます.
私たちはn 長さからpool (私たちの場合は3 )と追加r パラメータのデフォルト値はNone 我々は3つの要素のリストのすべての組み合わせを見て興味を持っているとしても3です.
また、それを保証する行がありますr は、iterable (リスト)
if r > n:
    return
次に、我々はindices and cycles . インデックスは基本的に各項目のインデックスです.サイクル使用range(n, n-r, -1) , どちらの場合ですかrange(3, 3-3, -1) ; これは3で始まり、ゼロで終わることを意味します.
次のコードのチャンクはwhile-loop これはリストの長さについて続きます.n 注意break このループから出るために下で.
アフターif-else サイクル、新しいセットindices は、pool , interableパラメータ入力.リスト内の要素の順序を変更します.
上のコメントで注意してください.cycles [ 3 , 2 , 1 ]で始まるindices [ 0 , 1 , 2 ]で起動します.コードをループごとに変更indices どこindices[i:] 連続的に長くなる[ 2 ]、[ 1 , 2 ]、それから、[ 1 , 2 , 3 ].中cycles それは[ 1 , 1 , 1 ]に向かって変化するので、コードがループから抜け出す点を示します.
while n:
        for i in reversed(range(r)):
            cycles[i] -= 1
            if cycles[i] == 0:
                indices[i:] = indices[i+1:] + indices[i:i+1]
                cycles[i] = n - i
            else:
                j = cycles[i]
                indices[i], indices[-j] = indices[-j], indices[i]
                yield tuple(pool[i] for i in indices[:r])
                break
        else:
            print("return:")
The permutations(iterable, r) 関数はgenerator それで、リストのすべての順列を印刷するためにもう一度それをループさせる必要があります.
<generator object permutations at 0x7fe19400fdd0>
すべての置換を出力するために、ループのために別のループを追加します.
perm = permutations(list1, 3)
count = 0

for p in perm:
    count += 1
    print(p)
print("there are:", count, "permutations.")
以下に結果を示します.

より明確な代替:再帰を用いた置換


よくあることだが、私が後に見たより良い方法があるthis stack overflow ( h/t to ):
def all_perms(elements):
    if len(elements) <= 1:
        yield elements  # Only permutation possible = no permutation
    else:
        # Iteration over the first element in the result permutation:
        for (index, first_elmt) in enumerate(elements):
            other_elmts = elements[:index] + elements[index+1:]
            for permutation in all_perms(other_elmts):
                yield [first_elmt] + permutation
The enumerate 組み込み関数は別に作成する必要がなくなりますcycles and indices . ローカル変数other_elmts リストの他の要素をfirst_elmt , 次に、ループのための2番目の再帰的に他の要素の置換を見つける前にfirst_elmt 最終行で、リストのすべての可能な置換を生成します.前の場合と同様に、この関数の結果はgenerator これには、ループを通して置換が必要です.
私は、これがドキュメント版より消化が簡単であるとわかりました.
あなたがあなたの製品を通していろいろなユーザー旅行をして、すべての可能な経路を理解したいとき、順列は役に立ちます.この短いPythonスクリプトを使えば、すべてのオプションを簡単にプリントアウトできます.

覚醒する


ユーザー漏斗の観点から、順列は、ユーザーが取るかもしれないすべての可能な経路を調査するのを許します.我々の仮説的な例では、3段階の漏斗は、ユーザがスタートからフィニッシュまで移動できる6つの経路をもたらす.
permutationを知っていることは、漏斗にもう一つの「ステップ」を加えるかどうかを決定するとき、我々に一時停止を与えなければなりません.つのステップ漏斗から4段の漏斗へ行くことは、6から24までの可能な経路の数を増やします-4倍の増加.
これはあなたのユーザと「エンドゴール」(変換)の間の摩擦をあなたの製品のためにあるかもしれません、しかし、それはまた、ユーザー経験で複雑さ(そして、潜在的混乱)を増やします.
データサイエンス、機械学習、R、パイソン、SQLとより多くのより多くの内容のために.