จะแปลงรายการอาร์เรย์ numpy เป็นอาร์เรย์ numpy เดียวได้อย่างไร


110

สมมติว่าฉันมี;

LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])] # inner lists are numpy arrays

ฉันพยายามที่จะแปลง

array([[1, 2, 3, 4, 5],
       [1, 2, 3, 4, 5],
       [1, 2, 3, 4, 5])

ฉันกำลังแก้ปัญหาโดยการวนซ้ำบน vstack ตอนนี้ แต่มันช้ามากสำหรับ LIST ขนาดใหญ่โดยเฉพาะ

คุณแนะนำอะไรสำหรับวิธีที่มีประสิทธิภาพสูงสุด


5
LIST = [[array([1, 2, 3, 4, 5]), array([1, 2, 3, 4, 5],[1,2,3,4,5])]นี่ไม่ใช่ไวยากรณ์ของ python ที่ถูกต้อง กรุณาชี้แจง.
Marcin

คำตอบ:


140

โดยทั่วไปคุณสามารถเชื่อมลำดับอาร์เรย์ทั้งหมดตามแกนใดก็ได้:

numpy.concatenate( LIST, axis=0 )

แต่คุณไม่ต้องกังวลเกี่ยวกับรูปร่างและมิติของแต่ละอาร์เรย์ในรายการ (สำหรับการส่งออก 3x5 2 มิติคุณต้องให้แน่ใจว่าพวกเขาทั้งหมด 2 มิติอาร์เรย์ n โดย 5 แล้ว) หากคุณต้องการเชื่อมอาร์เรย์ 1 มิติเข้าด้วยกันเป็นแถวของเอาต์พุต 2 มิติคุณต้องขยายมิติข้อมูล

ตามที่คำตอบของ Jorge ชี้ให้เห็นนอกจากนี้ยังมีฟังก์ชั่นที่stackแนะนำใน numpy 1.10:

numpy.stack( LIST, axis=0 )

สิ่งนี้ใช้แนวทางเสริม: สร้างมุมมองใหม่ของอาร์เรย์อินพุตแต่ละรายการและเพิ่มมิติพิเศษ (ในกรณีนี้คือทางด้านซ้ายดังนั้นnอาร์เรย์ 1D องค์ประกอบแต่ละตัวจะกลายเป็นอาร์เรย์ 1 by- n2D) ก่อนที่จะเชื่อมต่อกัน จะใช้ได้ก็ต่อเมื่ออาร์เรย์อินพุตทั้งหมดมีรูปร่างเหมือนกันแม้จะอยู่ตามแกนของการเรียงต่อกัน

vstack(หรือเทียบเท่าrow_stack) มักเป็นโซลูชันที่ใช้งานง่ายกว่าเนื่องจากจะใช้ลำดับของอาร์เรย์ 1 และ / หรือ 2 มิติและขยายขนาดโดยอัตโนมัติเมื่อจำเป็นและเฉพาะเมื่อจำเป็นก่อนที่จะเชื่อมรายการทั้งหมดเข้าด้วยกัน ในกรณีที่ต้องการมิติใหม่มิติข้อมูลจะถูกเพิ่มทางด้านซ้าย อีกครั้งคุณสามารถเชื่อมรายการทั้งหมดพร้อมกันโดยไม่จำเป็นต้องทำซ้ำ:

numpy.vstack( LIST )

ลักษณะการทำงานที่ยืดหยุ่นนี้ยังแสดงโดยทางลัดของไวยากรณ์numpy.r_[ array1, ...., arrayN ](สังเกตวงเล็บเหลี่ยม) นี้เป็นสิ่งที่ดีสำหรับการเชื่อมโยงไม่กี่อาร์เรย์อย่างชัดเจนมีชื่อ LISTแต่ไม่ดีสำหรับสถานการณ์ของคุณเพราะรูปแบบนี้จะไม่ยอมรับลำดับของอาร์เรย์เช่นคุณ

นอกจากนี้ยังมีฟังก์ชันcolumn_stackและช็อตคัทที่คล้ายคลึงกันc_[...]สำหรับการเรียงซ้อนในแนวนอน (คอลัมน์ที่ชาญฉลาด) ตลอดจนฟังก์ชันที่มีการบันทึกเกือบจะhstackด้วยเหตุผลบางประการข้อหลังมีความยืดหยุ่นน้อยกว่า (มีความเข้มงวดเกี่ยวกับมิติข้อมูลของอาร์เรย์อินพุตและพยายามที่จะเชื่อมต่อกัน อาร์เรย์ 1-D แบบ end-to-end แทนที่จะถือว่าเป็นคอลัมน์)

สุดท้ายในกรณีเฉพาะของการซ้อนอาร์เรย์ 1-D ในแนวตั้งสิ่งต่อไปนี้ยังใช้ได้:

numpy.array( LIST )

... เนื่องจากอาร์เรย์สามารถสร้างจากลำดับของอาร์เรย์อื่น ๆ ได้จึงเพิ่มมิติใหม่ให้กับจุดเริ่มต้น


5
ฉันคิดว่าเขาต้องการอาร์เรย์ 2d เป็นเอาต์พุต
Beefster

8

เริ่มต้นใน NumPy เวอร์ชัน 1.10 เรามีเมธอดสแต็ก สามารถซ้อนอาร์เรย์ของมิติใด ๆ (เท่ากันทั้งหมด):

# List of arrays.
L = [np.random.randn(5,4,2,5,1,2) for i in range(10)]

# Stack them using axis=0.
M = np.stack(L)
M.shape # == (10,5,4,2,5,1,2)
np.all(M == L) # == True

M = np.stack(L, axis=1)
M.shape # == (5,10,4,2,5,1,2)
np.all(M == L) # == False (Don't Panic)

# This are all true    
np.all(M[:,0,:] == L[0]) # == True
all(np.all(M[:,i,:] == L[i]) for i in range(10)) # == True

สนุก,


1

ฉันตรวจสอบวิธีการบางอย่างเพื่อประสิทธิภาพความเร็วและพบว่าไม่มีความแตกต่าง! ข้อแตกต่างเพียงอย่างเดียวคือการใช้วิธีการบางอย่างคุณต้องตรวจสอบมิติอย่างรอบคอบ

เวลา:

|------------|----------------|-------------------|
|            | shape (10000)  |  shape (1,10000)  |
|------------|----------------|-------------------|
| np.concat  |    0.18280     |      0.17960      |
|------------|----------------|-------------------|
|  np.stack  |    0.21501     |      0.16465      |
|------------|----------------|-------------------|
| np.vstack  |    0.21501     |      0.17181      |
|------------|----------------|-------------------|
|  np.array  |    0.21656     |      0.16833      |
|------------|----------------|-------------------|

อย่างที่คุณเห็นฉันลอง 2 การทดลอง - ใช้np.random.rand(10000)และnp.random.rand(1, 10000) และถ้าเราใช้อาร์เรย์ 2d มากกว่าnp.stackและnp.arrayสร้างมิติเพิ่มเติม - ผลลัพธ์รูปร่างคือ (1,10000,10000) และ (10,000,1,10000) ดังนั้นพวกเขาจึงต้องดำเนินการเพิ่มเติมเพื่อหลีกเลี่ยงสิ่งนี้ .

รหัส:

from time import perf_counter
from tqdm import tqdm_notebook
import numpy as np
l = []
for i in tqdm_notebook(range(10000)):
    new_np = np.random.rand(10000)
    l.append(new_np)



start = perf_counter()
stack = np.stack(l, axis=0 )
print(f'np.stack: {perf_counter() - start:.5f}')

start = perf_counter()
vstack = np.vstack(l)
print(f'np.vstack: {perf_counter() - start:.5f}')

start = perf_counter()
wrap = np.array(l)
print(f'np.array: {perf_counter() - start:.5f}')

start = perf_counter()
l = [el.reshape(1,-1) for el in l]
conc = np.concatenate(l, axis=0 )
print(f'np.concatenate: {perf_counter() - start:.5f}')
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.