Nhận giá trị tối thiểu thứ hai trên mỗi cột trong mảng 2D


15

Làm cách nào tôi có thể nhận được giá trị tối thiểu thứ hai từ mỗi cột? Tôi có mảng này:

A = [[72 76 44 62 81 31]
     [54 36 82 71 40 45]
     [63 59 84 36 34 51]
     [58 53 59 22 77 64]
     [35 77 60 76 57 44]]

Tôi muốn có đầu ra như:

A = [54 53 59 36 40 44]

bạn đã thử gì chưa ?
Meha Parekh

tối thiểu thứ hai trên mỗi cột ?
Nicolas Gervais

@NicolasGervais có
Ông Dan

Câu trả lời:


12

Hãy thử điều này, chỉ trong một dòng:

[sorted(i)[1] for i in zip(*A)]

trong hành động:

In [12]: A = [[72, 76, 44, 62, 81, 31], 
    ...:      [54 ,36 ,82 ,71 ,40, 45], 
    ...:      [63 ,59, 84, 36, 34 ,51], 
    ...:      [58, 53, 59, 22, 77 ,64], 
    ...:      [35 ,77, 60, 76, 57, 44]] 

In [18]: [sorted(i)[1] for i in zip(*A)]                                                                                                                                                                           
Out[18]: [54, 53, 59, 36, 40, 44]

zip(*A) sẽ hoán chuyển danh sách danh sách của bạn để các cột trở thành hàng.

và nếu bạn có giá trị trùng lặp, ví dụ:

In [19]: A = [[72, 76, 44, 62, 81, 31], 
    ...:  [54 ,36 ,82 ,71 ,40, 45], 
    ...:  [63 ,59, 84, 36, 34 ,51], 
    ...:  [35, 53, 59, 22, 77 ,64],   # 35
    ...:  [35 ,77, 50, 76, 57, 44],]  # 35

Nếu bạn cần bỏ qua cả hai 35, bạn có thể sử dụng set():

In [29]: [sorted(list(set(i)))[1] for i in zip(*A)]                                                                                                                                                                
Out[29]: [54, 53, 50, 36, 40, 44]

6

Các thao tác trên numpymảng nên được thực hiện với các numpyhàm, vì vậy hãy xem cái này:

np.sort(A, axis=0)[1, :]
Out[61]: array([54, 53, 59, 36, 40, 44])

Đây phải là giải pháp tốt nhất theo như tôi biết, nó giữ mọi thứ trong đó numpy, tôi nghĩ rằng giải pháp lambdaphải làm chậm lại heapq.nsmallest. Có vẻ tốt nhất để giữ mọi thứ nhanh chóngnumpy
jamylak

3

bạn có thể sử dụng heapq.nsmallest

from heapq import nsmallest

[nsmallest(2, e)[-1] for e in zip(*A)]

đầu ra:

[54, 53, 50, 36, 40, 44]

Tôi đã thêm một điểm chuẩn đơn giản để so sánh hiệu suất của các giải pháp khác nhau đã được đăng:

nhập mô tả hình ảnh ở đây

from simple_benchmark import BenchmarkBuilder
from heapq import nsmallest


b = BenchmarkBuilder()

@b.add_function()
def MehrdadPedramfar(A):
    return [sorted(i)[1] for i in zip(*A)]

@b.add_function()
def NicolasGervais(A):
    return np.sort(A, axis=0)[1, :]

@b.add_function()
def imcrazeegamerr(A):
    rotated = zip(*A[::-1])

    result = []
    for arr in rotated:
        # sort each 1d array from min to max
        arr = sorted(list(arr))
        # add the second minimum value to result array
        result.append(arr[1])

    return result

@b.add_function()
def Daweo(A):
    return np.apply_along_axis(lambda x:heapq.nsmallest(2,x)[-1], 0, A)

@b.add_function()       
def kederrac(A):
    return [nsmallest(2, e)[-1] for e in zip(*A)]


@b.add_arguments('Number of row/cols (A is  square matrix)')
def argument_provider():
    for exp in range(2, 18):
        size = 2**exp
        yield size, [[randint(0, 1000) for _ in range(size)] for _ in range(size)]

r = b.run()
r.plot()

Sử dụng zipvới sortedchức năng là giải pháp nhanh nhất cho danh sách 2d nhỏ trong khi sử dụng zipvới heapq.nsmallestchương trình là tốt nhất trong danh sách 2d lớn


1
Chỉ là một suy nghĩ hoang dã: những kết quả này có thể bị ảnh hưởng bởi thực tế là bạn đã tạo ra những con số không phải là dtypes không? Ngoài ra, sẽ không được xây dựng trong randint trả về một danh sách thay vì một mảng?
Nicolas Gervais

1

Tôi hy vọng tôi hiểu chính xác câu hỏi của bạn nhưng dù bằng cách nào thì đây là giải pháp của tôi, tôi chắc chắn có một cách thanh lịch hơn để làm điều này nhưng nó hoạt động

A = [[72,76,44,62,81,31]
 ,[54,36,82,71,40,45]
 ,[63,59,84,36,34,51]
 ,[58,53,59,22,77,64]
 ,[35,77,50,76,57,44]]

#rotate the array 90deg
rotated = zip(*A[::-1])

result = []
for arr in rotated:
    # sort each 1d array from min to max
    arr = sorted(list(arr))
    # add the second minimum value to result array
    result.append(arr[1])
print(result)

nhập mô tả hình ảnh ở đây


0

Giả sử đó Anumpy.array(nếu điều này đúng, vui lòng xem xét thêm numpythẻ vào câu hỏi của bạn) thì bạn có thể sử dụng apply_along_axischo cách sau:

import heap
import numpy as np
A = np.array([[72, 76, 44, 62, 81, 31],
              [54, 36, 82, 71, 40, 45],
              [63, 59, 84, 36, 34, 51],
              [58, 53, 59, 22, 77, 64],
              [35, 77, 60, 76, 57, 44]])
second_mins = np.apply_along_axis(lambda x:heapq.nsmallest(2,x)[-1], 0, A)
print(second_mins)  # [54 53 59 36 40 44]

Lưu ý rằng tôi đã sử dụng heapq.nsmallest vì nó sắp xếp nhiều như yêu cầu để có được 2 phần tử nhỏ nhất, không giống như sortedsắp xếp hoàn chỉnh.


0
>>> A = np.arange(30).reshape(5,6).tolist()
>>> A
[[0, 1, 2, 3, 4, 5], 
 [6, 7, 8, 9, 10, 11], 
 [12, 13, 14, 15, 16, 17], 
 [18, 19, 20, 21, 22, 23],
 [24, 25, 26, 27, 28, 29]]

Đã cập nhật : Sử dụng setđể ngăn chặn danh sách trùng lặp và chuyển đổi bằng cách sử dụngzip(*A)

>>> [sorted(set(items))[1] for items in zip(*A)]
[6, 7, 8, 9, 10, 11]

cũ: mục tối thiểu thứ hai trong mỗi hàng

>>> [sorted(set(items))[1] for items in A]
[1, 7, 13, 19, 25]

Không phải là nhận được mục thứ hai trong mỗi hàng chứ không phải cột?
paxdiablo

@paxdiablo Vâng cảm ơn đã thông báo. cập nhật câu trả lời.
Dishin H Goyani
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.