2D 배열에서 열당 두 번째 최소값 가져 오기


15

각 열에서 두 번째 최소값을 어떻게 얻을 수 있습니까? 이 배열이 있습니다.

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]]

다음과 같은 출력을 원합니다.

A = [54 53 59 36 40 44]

당신은 아무것도 시도 했습니까? ?
Meha Parekh

제 최소 열당 ?
Nicolas Gervais

@NicolasGervais yes
Mr Dan

답변:


12

한 줄로 시도해보십시오.

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

행동 :

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) 열이 행이되도록 목록 목록을 바꿉니다.

예를 들어 중복 값이있는 경우

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

두 가지를 모두 건너 뛰 35려면 다음을 사용할 수 있습니다 set().

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

6

numpy배열 에 대한 작업은 numpy함수를 사용하여 수행해야 하므로 다음을 살펴보십시오.

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

이것은 내가 아는 한 최선의 해결책 이어야합니다 . 모든 것을 유지합니다 numpy. 나는 솔루션을 lambda느리게해야 한다고 생각합니다 heapq.nsmallest. 빨리 모든 것을 유지하는 가장 좋은 것 같다numpy
jamylak

3

heapq.nsmallest 를 사용할 수 있습니다

from heapq import nsmallest

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

산출:

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

이미 게시 한 다른 솔루션의 성능을 비교하기 위해 간단한 벤치 마크를 추가했습니다.

여기에 이미지 설명을 입력하십시오

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()

기능을 사용 zip하는 sorted것은 작은 2D 목록을위한 가장 빠른 솔루션 인 반면 쇼를 사용 zip하면 heapq.nsmallest큰 2D 목록을 최고로 사용할 수 있습니다


1
야만적 인 생각 :이 결과가 당신이 멍청한 dtypes가 아닌 숫자를 생성했다는 사실에 영향을받을 수 있습니까? 또한 내장 randint가 배열 대신 목록을 반환하지 않습니까?
니콜라스 게르 바이

1

나는 당신의 질문을 올바르게 이해하기를 희망하지만 여기에 내 해결책이 있습니다.이를 수행하는 더 elegent 방법이 있는지 확인하지만 작동합니다.

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)

여기에 이미지 설명을 입력하십시오


0

즉 가정 A입니다 numpy.array(이것은 사실이 보유하고있는 경우 추가 고려하시기 바랍니다 numpy귀하의 질문에 태그를) 다음 사용할 수있는 apply_along_axis그 다음 방법을 :

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]

완전한 정렬을 수행하는 것과 달리 가장 작은 2 개의 요소를 가져 오는 데 필요한만큼 정렬하는 것처럼 heapq.nsmallest 를 사용 했습니다 sorted.


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]]

업데이트 : set목록을 사용하여 중복 및 조옮김 방지zip(*A)

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

old : 각 행의 두 번째 최소 항목

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

열이 아닌 각 행에서 두 번째 항목을 가져 오지 않습니까?
paxdiablo

@paxdiablo 네, 감사합니다. 업데이트 된 답변.
Dishin H Goyani
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.