দুটি অ্যারের সমস্ত সংমিশ্রণের একটি অ্যারে তৈরি করতে ন্যাপি ব্যবহার করে


143

আমি এটির সাথে জটিল কিছু করার চেষ্টা করার আগে এটির সংখ্যাগত আচরণটি অধ্যয়নের জন্য 6 টি প্যারামিটার ফাংশনের পরামিতিগুলির স্থানটি চালানোর চেষ্টা করছি তাই এটি করার জন্য আমি একটি কার্যকর উপায় অনুসন্ধান করছি।

আমার ফাংশনটি ইনপুট হিসাবে 6-ম্লান নিম্পি অ্যারে প্রদানে ভাসমান মান নেয়। আমি প্রথমে যা করার চেষ্টা করেছি তা হ'ল:

প্রথমে আমি একটি ফাংশন তৈরি করেছি যা 2 টি অ্যারে নেয় এবং দুটি অ্যারে থেকে মানগুলির সংমিশ্রণ সহ একটি অ্যারে উত্পন্ন করে

from numpy import *
def comb(a,b):
    c = []
    for i in a:
        for j in b:
            c.append(r_[i,j])
    return c

তারপরে আমি reduce()একই অ্যারের এম কপিগুলিতে এটি প্রয়োগ করতাম :

def combs(a,m):
    return reduce(comb,[a]*m)

এবং তারপরে আমি আমার ফাংশনটি এর মতো মূল্যায়ন করি:

values = combs(np.arange(0,1,0.1),6)
for val in values:
    print F(val)

এটি কাজ করে তবে এটি খুব ধীর হয়ে আছে। আমি জানি পরামিতিগুলির স্থানটি বিশাল, তবে এটি এত ধীরে হওয়া উচিত নয়। আমি এই উদাহরণে কেবল 10 6 (এক মিলিয়ন) পয়েন্ট স্যাম্পল করেছি এবং অ্যারে তৈরি করতে এটি 15 সেকেন্ডেরও বেশি সময় নিয়েছে values

আপনি কি নামপাক দিয়ে এটি করার আরও কার্যকর উপায় জানেন?

Fযদি প্রয়োজন হয় তবে ফাংশনটি যেভাবে আর্গুমেন্ট গ্রহণ করে তা আমি সংশোধন করতে পারি ।


আমি খুঁজে পাওয়া দ্রুততম কার্টেসিয়ান পণ্যটির জন্য, এই উত্তরটি দেখুন । (যেহেতু এই প্রশ্নের থেকে প্রশ্নটি আলাদাভাবে বর্ণিত হয়েছে, তাই আমি মনে করি যে প্রশ্নগুলি সদৃশ নয়, তবে দুটি প্রশ্নের সর্বোত্তম সমাধান একই))
প্রেরক

উত্তর:


127

numpy(> 1.8.x) এর নতুন সংস্করণে numpy.meshgrid()আরও দ্রুত বাস্তবায়ন সরবরাহ করে:

@ পিভির সমাধান

In [113]:

%timeit cartesian(([1, 2, 3], [4, 5], [6, 7]))
10000 loops, best of 3: 135 µs per loop
In [114]:

cartesian(([1, 2, 3], [4, 5], [6, 7]))

Out[114]:
array([[1, 4, 6],
       [1, 4, 7],
       [1, 5, 6],
       [1, 5, 7],
       [2, 4, 6],
       [2, 4, 7],
       [2, 5, 6],
       [2, 5, 7],
       [3, 4, 6],
       [3, 4, 7],
       [3, 5, 6],
       [3, 5, 7]])

numpy.meshgrid()শুধুমাত্র 2 ডি হিসাবে ব্যবহার করুন, এখন এটি এনডি সক্ষম। এই ক্ষেত্রে, 3 ডি:

In [115]:

%timeit np.array(np.meshgrid([1, 2, 3], [4, 5], [6, 7])).T.reshape(-1,3)
10000 loops, best of 3: 74.1 µs per loop
In [116]:

np.array(np.meshgrid([1, 2, 3], [4, 5], [6, 7])).T.reshape(-1,3)

Out[116]:
array([[1, 4, 6],
       [1, 5, 6],
       [2, 4, 6],
       [2, 5, 6],
       [3, 4, 6],
       [3, 5, 6],
       [1, 4, 7],
       [1, 5, 7],
       [2, 4, 7],
       [2, 5, 7],
       [3, 4, 7],
       [3, 5, 7]])

মনে রাখবেন চূড়ান্ত ফলাফলের ক্রমটি কিছুটা আলাদা।


14
np.stack(np.meshgrid([1, 2, 3], [4, 5], [6, 7]), -1).reshape(-1, 3)সঠিক অর্ডার দেবে
এরিক

@ সিটি ঝু এটির রূপান্তর করার কোন সহজ উপায় আছে যাতে ম্যাট্রিক্স কলাম হিসাবে বিভিন্ন অ্যারে ধারণ করে পরিবর্তে ইনপুট হিসাবে ব্যবহৃত হয়?
দোল

2
এটি লক্ষ্য করা উচিত যে জালগ্রিডটি কেবল ছোট পরিসরের সেটগুলির জন্য কাজ করে, আমার একটি বড় রয়েছে এবং আমি ত্রুটি পেয়েছি: ভ্যালু এরির: একটি নাদারের সর্বাধিক সমর্থিত মাত্রা 32, পাওয়া গেছে 69
মিকম

158

এখানে একটি খাঁটি-অদ্ভুত বাস্তবায়ন। এটির ব্যবহারগুলি তুলনায় প্রায় 5 × দ্রুত।


import numpy as np

def cartesian(arrays, out=None):
    """
    Generate a cartesian product of input arrays.

    Parameters
    ----------
    arrays : list of array-like
        1-D arrays to form the cartesian product of.
    out : ndarray
        Array to place the cartesian product in.

    Returns
    -------
    out : ndarray
        2-D array of shape (M, len(arrays)) containing cartesian products
        formed of input arrays.

    Examples
    --------
    >>> cartesian(([1, 2, 3], [4, 5], [6, 7]))
    array([[1, 4, 6],
           [1, 4, 7],
           [1, 5, 6],
           [1, 5, 7],
           [2, 4, 6],
           [2, 4, 7],
           [2, 5, 6],
           [2, 5, 7],
           [3, 4, 6],
           [3, 4, 7],
           [3, 5, 6],
           [3, 5, 7]])

    """

    arrays = [np.asarray(x) for x in arrays]
    dtype = arrays[0].dtype

    n = np.prod([x.size for x in arrays])
    if out is None:
        out = np.zeros([n, len(arrays)], dtype=dtype)

    m = n / arrays[0].size
    out[:,0] = np.repeat(arrays[0], m)
    if arrays[1:]:
        cartesian(arrays[1:], out=out[0:m, 1:])
        for j in xrange(1, arrays[0].size):
            out[j*m:(j+1)*m, 1:] = out[0:m, 1:]
    return out

47
কখনই এটিকে জমা দেওয়ার জন্য নিমপকে অন্তর্ভুক্ত করার কথা বিবেচনা করবেন? এই কার্যকারিতাটি অনুসন্ধান করতে গিয়ে আমি আপনার পোস্টটি খুঁজে পেলাম না।
এন্ডোলিথ

1
এই বাস্তবায়নে বাগ রয়েছে। স্ট্রিংগুলির অ্যারেগুলির উদাহরণস্বরূপ: অ্যারে [0] .dtype = "| এস 3" এবং অ্যারে [1] .dtype = "| এস 5"। সুতরাং ইনপুটটিতে দীর্ঘতম স্ট্রিং সন্ধান করার প্রয়োজন আছে এবং এর প্রকারটি = np.zeros ([n, লেন (অ্যারে)), dtype = dtype) এ ব্যবহার করুন
নর্সেস করুন

38
এফওয়াইআই: মনে হয় এটি এটিকে বিজ্ঞান-শিখার প্যাকেজে পরিণত করেছেfrom sklearn.utils.extmath import cartesian
গাস

2
আমি ঠিক বুঝতে পেরেছি: এটি itertools.combitions থেকে কিছুটা আলাদা, কারণ এই ফাংশনটি মানগুলির ক্রমকে সম্মান করে যেখানে সংমিশ্রণগুলি হয় না, সুতরাং এই ফাংশনটি সংমিশ্রণের চেয়ে বেশি মান প্রদান করে। এখনও খুব চিত্তাকর্ষক, তবে দুর্ভাগ্যক্রমে আমি যা খুঁজছিলাম তা নয় :(
ডেভিড মার্কস

6
TypeError: slice indices must be integers or None or have an __index__ methodদ্বারা নিক্ষিপ্তcartesian(arrays[1:], out=out[0:m,1:])
বোর্ন

36

itertools.combitions সাধারণত পাইথন কনটেইনার থেকে কম্বিনেশনগুলি পাওয়ার দ্রুততম উপায় (যদি আপনি বাস্তবে সংমিশ্রণগুলি চান, তবে পুনরাবৃত্তির সাথে বিন্যাস এবং স্বাধীনভাবে বিন্যাস ব্যতীত ব্যবস্থাগুলি; এটি আপনার কোডটি করছে বলে মনে হচ্ছে না, তবে আমি করতে পারি না) আপনার কোডটি বগী হওয়ার কারণে বা আপনি ভুল পরিভাষা ব্যবহার করছেন বলেই তা বলুন।

আপনি যদি সংযোজনগুলির চেয়ে ভিন্ন কিছু চান তবে সম্ভবত এটির তাত্ত্বিকগুলিতে অন্যান্য পুনরাবৃত্তকারী productবা permutations, আপনাকে আরও ভালভাবে পরিবেশন করতে পারে। উদাহরণস্বরূপ, দেখে মনে হচ্ছে আপনার কোডটি মোটামুটি একই রকম:

for val in itertools.product(np.arange(0, 1, 0.1), repeat=6):
    print F(val)

এই পুনরাবৃত্তকারীগুলির সমস্তগুলিই তালিকাগুলি সরবরাহ করে, তালিকা বা আকাঙ্ক্ষিত অ্যারে নয়, সুতরাং যদি আপনার এফ নির্দিষ্টভাবে একটি নমপি অ্যারে পাওয়ার বিষয়ে পছন্দসই হয় তবে আপনাকে প্রতিটি পদক্ষেপে একটি নির্মাণ বা সাফ করার এবং পুনরায় পূরণের অতিরিক্ত ওভারহেড গ্রহণ করতে হবে।


8

আপনি এরকম কিছু করতে পারেন

import numpy as np

def cartesian_coord(*arrays):
    grid = np.meshgrid(*arrays)        
    coord_list = [entry.ravel() for entry in grid]
    points = np.vstack(coord_list).T
    return points

a = np.arange(4)  # fake data
print(cartesian_coord(*6*[a])

যা দেয়

array([[0, 0, 0, 0, 0, 0],
   [0, 0, 0, 0, 0, 1],
   [0, 0, 0, 0, 0, 2],
   ..., 
   [3, 3, 3, 3, 3, 1],
   [3, 3, 3, 3, 3, 2],
   [3, 3, 3, 3, 3, 3]])

2
জালগ্রিডের জন্য 32 টিরও বেশি অ্যারে গ্রহণের জন্য নুমপাইয়ের কী উপায় আছে? যতক্ষণ আমি 32 টির বেশি অ্যারে পাস না করি ততক্ষণ এই পদ্ধতিটি আমার পক্ষে কাজ করে।
জোয়েলমব

8

নিম্নলিখিত নাম্বার বাস্তবায়ন প্রায় হওয়া উচিত। প্রদত্ত উত্তরের গতি 2x:

def cartesian2(arrays):
    arrays = [np.asarray(a) for a in arrays]
    shape = (len(x) for x in arrays)

    ix = np.indices(shape, dtype=int)
    ix = ix.reshape(len(arrays), -1).T

    for n, arr in enumerate(arrays):
        ix[:, n] = arrays[n][ix[:, n]]

    return ix

1
ভাল লাগছে। আমার প্রাথমিক পরীক্ষাগুলি দ্বারা, এটি সমস্ত জোড়া, ট্রিপল এবং-1,2, ..., 100 up এর 4-টিপলগুলির মূল উত্তরের চেয়ে দ্রুত দেখায়} এর পরে, আসল উত্তরটি জিতল। এছাড়াও, ভবিষ্যতের পাঠকগণ k 1, ..., n} এর সমস্ত কে-টিপলস তৈরি করতে চেয়েছেন np.indices((n,...,n)).reshape(k,-1).Twill
জেএমই

এটি কেবল পূর্ণসংখ্যার জন্য কাজ করে, যখন গৃহীত উত্তরটিও ভাসমানদের জন্য কাজ করে।
এফজেসি

7

দেখে মনে হচ্ছে আপনি নিজের ফাংশনটি মূল্যায়নের জন্য গ্রিড চান, সেক্ষেত্রে আপনি numpy.ogrid(উন্মুক্ত) বা numpy.mgrid(মাংসপেশী ) ব্যবহার করতে পারেন :

import numpy
my_grid = numpy.mgrid[[slice(0,1,0.1)]*6]


4

খাঁটি নম্পপি ব্যবহার করে এখানে আর কোনও উপায় নেই, কোনও পুনরাবৃত্তি হবে না, তালিকার কোনও উপলব্ধি নেই এবং লুপগুলির জন্য স্পষ্ট নয়। এটি মূল উত্তরের চেয়ে প্রায় 20% ধীর এবং এটি এনপি.মেশগ্রিডের উপর ভিত্তি করে।

def cartesian(*arrays):
    mesh = np.meshgrid(*arrays)  # standard numpy meshgrid
    dim = len(mesh)  # number of dimensions
    elements = mesh[0].size  # number of elements, any index will do
    flat = np.concatenate(mesh).ravel()  # flatten the whole meshgrid
    reshape = np.reshape(flat, (dim, elements)).T  # reshape and transpose
    return reshape

উদাহরণ স্বরূপ,

x = np.arange(3)
a = cartesian(x, x, x, x, x)
print(a)

দেয়

[[0 0 0 0 0]
 [0 0 0 0 1]
 [0 0 0 0 2]
 ..., 
 [2 2 2 2 0]
 [2 2 2 2 1]
 [2 2 2 2 2]]

3

1 ডি অ্যারে (বা সমতল পাইথন তালিকাগুলি) এর কার্টেসিয়ান পণ্যটির খাঁটি নকল প্রয়োগের জন্য, কেবল meshgrid()অক্ষগুলি ব্যবহার করুন transpose(), এবং পছন্দসই আউটপুটটিতে পুনরায় আকার দিন:

 def cartprod(*arrays):
     N = len(arrays)
     return transpose(meshgrid(*arrays, indexing='ij'), 
                      roll(arange(N + 1), -1)).reshape(-1, N)

দ্রষ্টব্য এটির গত অক্ষগুলি দ্রুততম পরিবর্তনের ("সি স্টাইল" বা "সারি-প্রধান") এর সম্মেলন রয়েছে।

In [88]: cartprod([1,2,3], [4,8], [100, 200, 300, 400], [-5, -4])
Out[88]: 
array([[  1,   4, 100,  -5],
       [  1,   4, 100,  -4],
       [  1,   4, 200,  -5],
       [  1,   4, 200,  -4],
       [  1,   4, 300,  -5],
       [  1,   4, 300,  -4],
       [  1,   4, 400,  -5],
       [  1,   4, 400,  -4],
       [  1,   8, 100,  -5],
       [  1,   8, 100,  -4],
       [  1,   8, 200,  -5],
       [  1,   8, 200,  -4],
       [  1,   8, 300,  -5],
       [  1,   8, 300,  -4],
       [  1,   8, 400,  -5],
       [  1,   8, 400,  -4],
       [  2,   4, 100,  -5],
       [  2,   4, 100,  -4],
       [  2,   4, 200,  -5],
       [  2,   4, 200,  -4],
       [  2,   4, 300,  -5],
       [  2,   4, 300,  -4],
       [  2,   4, 400,  -5],
       [  2,   4, 400,  -4],
       [  2,   8, 100,  -5],
       [  2,   8, 100,  -4],
       [  2,   8, 200,  -5],
       [  2,   8, 200,  -4],
       [  2,   8, 300,  -5],
       [  2,   8, 300,  -4],
       [  2,   8, 400,  -5],
       [  2,   8, 400,  -4],
       [  3,   4, 100,  -5],
       [  3,   4, 100,  -4],
       [  3,   4, 200,  -5],
       [  3,   4, 200,  -4],
       [  3,   4, 300,  -5],
       [  3,   4, 300,  -4],
       [  3,   4, 400,  -5],
       [  3,   4, 400,  -4],
       [  3,   8, 100,  -5],
       [  3,   8, 100,  -4],
       [  3,   8, 200,  -5],
       [  3,   8, 200,  -4],
       [  3,   8, 300,  -5],
       [  3,   8, 300,  -4],
       [  3,   8, 400,  -5],
       [  3,   8, 400,  -4]])

আপনি যদি প্রথম অক্ষটি দ্রুততম ("ফরট্রান শৈলী" বা "কলাম-মেজর") পরিবর্তন করতে চান তবে কেবল এই জাতীয় orderপ্যারামিটারটি পরিবর্তন করুন reshape():reshape((-1, N), order='F')


1

পান্ডস mergeসমস্যার একটি নিষ্পাপ, দ্রুত সমাধান প্রস্তাব:

# given the lists
x, y, z = [1, 2, 3], [4, 5], [6, 7]

# get dfs with same, constant index 
x = pd.DataFrame({'x': x}, index=np.repeat(0, len(x))
y = pd.DataFrame({'y': y}, index=np.repeat(0, len(y))
z = pd.DataFrame({'z': z}, index=np.repeat(0, len(z))

# get all permutations stored in a new df
df = pd.merge(x, pd.merge(y, z, left_index=True, righ_index=True),
              left_index=True, right_index=True)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.