2017-12-20 1 views
1

도움을 주신 모든 분들께 감사드립니다. 무엇이 가장 간결하게 내 문제를 설명하는 것 같습니다 우편 번호은 목록이 아닌 튜플의 반복자를 반환하므로 불변입니다. 아래의 작업 솔루션과 그 아래의 원래 질문 코드를 볼 수 있습니다.for 루프에서 zip을 사용하여 수치스러운 배열에 할당

솔루션 :

f = np.array([1,2,3,4,5,6,7,8,9,10]) 
trials = [[0,1,2], [5,6,7], [8,9]] 
trial_averages = [] 
for i in trials: 
    a = 0 
    for j in i: 
     a += f[j] 
    a /= len(i) 
    trial_averages.append(a) 
trial_averages = np.array(trial_averages) 
print('trials = {0}'.format(trials)) 
print('averages = {0}'.format(trial_averages)) 

trials = [[0, 1, 2], [5, 6, 7], [8, 9]] 
averages = [ 2. 7. 9.5] 

질문 : 두 개의 배열의 우편 및 수정 된 배열 for 루프에서 NumPy와 배열의 요소를 수정하려고

점점되지 업데이트되었습니다. 내가 뭘 놓치고 있니?

원본 예제가 정확한 문제를 설명하지 못했기 때문에 새로운 예제를 만들었습니다.

새로운 예제

f = np.array([1,2,3,4,5,6,7,8,9,10]) 
trials = [[0,1,2], [5,6,7], [8,9]] 
trial_averages = np.zeros(len(trials)) 
for i, j in zip(trials, trial_averages): 
    for k in i: 
     j += f[k] 
    j /= len(i) 
print('trials = {0}'.format(trials)) 
print('averages = {0}'.format(trial_averages)) 
print('{0}, {1}'.format(i, j)) 

출력 :

이때
trials = [[0, 1, 2], [5, 6, 7], [8, 9]] 
averages = [ 0. 0. 0. 0.] 
[8, 9], 9.5 

J는 I 번째 업데이트 될 것으로 예상 trial_averages의 요소에 대한 포인터이며 for 루프를 f의 값으로 합한 값이 이고 인 div 다음에 div로 표시됩니다. 목록의 길이에 따라 시험에서으로 각 시험에서 f의 값의 평균을 계산. 참조


오래 예 :

동작 예 :

A = np.array([1, 2, 3, 4], dtype=float) 
B = np.zeros(len(A)) 
for i, j in zip(A, B): 
    j = i 
print('A = {0}'.format(A)) 
print('B = {0}'.format(B)) 
print('{0}, {1}'.format(i, j)) 

출력 :

A = [ 1. 2. 3. 4.] 
B = [ 0. 0. 0. 0.] 
4.0, 4.0 

가 지퍼 입력 배열의 요소 포인터를 통과하지? 과제 j = i는 B = [1. 2. 3. 4.]?

도움 주셔서 감사합니다.

+0

_Doesn't 지퍼가 입력 배열의 요소에 대한 포인터를 전달을 _ 그것이 작동하지 않을 않았더라도 때문에'J = 나는'j '라는 이름을'i '라는 이름에 묶여있는 것 이외의 것을 아무것도하지 않는다. –

답변

1

은 당신이 할 때 발생하는 알고 할당. 변수에 새 객체를 지정합니까 아니면 객체 (변경 가능)를 수정합니까?

코드에서 j은 1d 배열의 요소입니다. 그러나 j=i은 에 할당 된 동일한 개체 인 j에 할당됩니다. 이것은 반복에 의해 생성 된 객체와의 모든 연결을 끊습니다. 2 차원 어레이의 행을 반복하는 반면에

:

In [439]: A = np.arange(12).reshape(3,4) 
In [440]: B = np.zeros_like(A) 
In [441]: for i, j in zip(A,B): 
    ...:  print(i, j) 
    ...:  j[...] = i 
    ...:  
[0 1 2 3] [0 0 0 0] 
[4 5 6 7] [0 0 0 0] 
[ 8 9 10 11] [0 0 0 0] 
In [442]: B 
Out[442]: 
array([[ 0, 1, 2, 3], 
     [ 4, 5, 6, 7], 
     [ 8, 9, 10, 11]]) 
여기

, ij 1D 배열은, 각각의 2 차원 배열도이다. j[...] =...j 배열의 값을 변경하므로 상위 배열 B에 반영됩니다. 이 규칙은 어떻게 변경 백 전파 부모가 다른 불구하고,뿐만 아니라 목록에 반복을 적용하는 것이

In [444]: for i, j in zip(A,B): 
    ...:  j += i 

참고 :

+=

B에 같은 변화를 생산, 다른 현재 위치에서 작업입니다 . 따라서 j=ij[:]=i의 차이점을 이해하는 것이 중요합니다. 동시에, 이런 방식으로 배열을 사용하는 습관에 빠지지 마십시오. 배열을 반복하지 않고 작업을 수행하십시오.

목록 예 :

In [446]: Al = A.tolist(); Bl = B.tolist() 
In [447]: for i,j in zip(Al, Bl): 
    ...:  j[:] = i[::-1] # assign a reverse list 
    ...:  # j = would not work 
In [449]: Bl 
Out[449]: [[3, 2, 1, 0], [7, 6, 5, 4], [11, 10, 9, 8]] 

변경하려고하는 값은 1 차원 배열의 요소이다. 그들은 (A NumPy와의 DTYPE에 싸여 있지만) 효과적으로 스칼라 :

In [455]: x=np.arange(3).astype(np.float64) 
In [456]: for j in x: 
    ...:  print(j,type(j)) 
    ...:  j += 1 
    ...:  print(j) 
    ...:  
0.0 <class 'numpy.float64'> 
1.0 
1.0 <class 'numpy.float64'> 
2.0 
2.0 <class 'numpy.float64'> 
3.0 
In [457]: x 
Out[457]: array([ 0., 1., 2.]) 

또는 단순 목록의 요소에 대한

:

In [462]: x=[0,1,2] 
In [463]: for j in x: 
    ...:  j += 1 
    ...:  
In [464]: x 
Out[464]: [0, 1, 2] 

내 예에서 난 그냥 2 차원 배열의 행을 변경 위. 값은 루프 내에서 변경되지만 소스 배열에 백 프로 그지하지 않습니다.

다른 예 :

In [469]: x = np.arange(3) 
In [470]: y = x[0] 
In [471]: y += 1 
In [472]: y 
Out[472]: 1 
In [473]: x 
Out[473]: array([0, 1, 2]) 
In [474]: x[0] += 1 
In [475]: x 
Out[475]: array([1, 1, 2]) 

반복 해 j가 더 x[0]+= 하나보다 y=x[0] 경우와 같다.

+0

통찰력을 가져 주셔서 감사합니다. 이름 할당 문제를 이해하고 있다고 생각합니다. 그런 점을 염두에두고 필자는 필자가 겪고있는 문제를보다 잘 반영 할 수 있도록 예제를 업데이트했습니다. 가능한 한 살펴보십시오. * + = * 및 */= *를 사용하고 있으므로 기본 값이 업데이트되어서는 안됩니까? – Seth

+0

예제에서 소스는 2d이고 'j'는 1d 배열입니다. 귀하의 경우 1 차원 어레이와 '스칼라'값. 차이점을 보여줄 수있는 몇 가지 예를 추가했습니다. – hpaulj

0

는 둘째

루프

의에서 인덱스를 다시 나쁜 생각입니다 당신 루프가 작성된도 B도 몸에 있기 때문에,

0

파이썬은 정말 없습니다 "C-로 아무것도 달성하지 스타일 "포인터가 있지만 객체를 가리킬 수있는 이름입니다. 때때로 객체가 변경 될 수 있으므로 이름이 참조하는 데이터가 변경됩니다 (변경 가능한 객체). 때로는 객체가 할 수없는 경우가 있으므로 새로운 객체를 만들고 그 객체에 이름을 다시 지정해야합니다 (불변 객체).

루프에 ij에 바인딩하는 zip의 출력은 변경할 수없는 값입니다.j = i을 말하는 것은 단지 이름 i에서j지적하지만, 이전 (여전히 B의 한 부분으로 존재하는) j로 알려진 개체에 아무것도하지 않습니다. 당신이 주변에 배열의 일부를 복사 한 후 NumPy와는 매우 효율적으로 당신을 위해 그것을 할 수있는 조각을 사용하려면

(Indexing — NumPy User Guide 참조)이 중요하다 파이썬에서

A = np.array([1, 2, 3, 4]) 
B = np.zeros_like(A) 
assert np.all(B == 0) 
B[:] = A[:] 
assert not np.any(B == 0) 
0

최소한의 변경 (화살표)으로 예제를 작동시키는 방법은 다음과 같습니다. 더 원칙적인 방법에 대한이 게시물의 하단을 참조하십시오

import numpy as np 

f = [1,2,3,4,5,6,7,8,9,10] 
trials = [[0,1,2], [5,6,7], [8,9]] 
trial_averages = np.zeros(len(trials)) 
for i, j in zip(trials, trial_averages[:, None]): # <---- 
    for k in i: 
     j += f[k] 
    j /= len(i) 
print('trials = {0}'.format(trials)) 
print('averages = {0}'.format(trial_averages)) 
print('{0}, {1}'.format(i, j)) 

A = np.array([1, 2, 3, 4], dtype=float) 
B = np.zeros(len(A)) 
for i, j in zip(A, B[:, None]):     # <---- 
    j[...] = i         # <---- 
print('A = {0}'.format(A)) 
print('B = {0}'.format(B)) 
print('{0}, {1}'.format(i, j)) 

출력 : 첫 번째 예에서 볼 수 있듯이

trials = [[0, 1, 2], [5, 6, 7], [8, 9]] 
averages = [ 2. 7. 9.5] 
[8, 9], [ 9.5] 
A = [ 1. 2. 3. 4.] 
B = [ 1. 2. 3. 4.] 
4.0, [ 4.] 

j가 변경할 수 있도록 충분하다. 두 번째 예에서 할당을 __setitem__으로 변경해야합니다.

C 포인터와 같은 무언가를 생성하는 좀 더 자세한 방법은 덜 익숙한 방법입니다. np.nditer을 사용하여 0 이외의 배열을 반환하는 반복자를 만들 수 있습니다. 여러면에서 스칼라처럼 동작하지만 [()]을 사용하여 "참조 해제"한 다음 할당 할 수 있습니다. 두 번째 예는 다음과 같이 전과 같은 출력을 생성 할 것이다 :

ro, wo, rw = ['readonly'], ['writeonly'], ['readwrite'] 

A = np.array([1, 2, 3, 4], dtype=float) 
B = np.zeros(len(A)) 
for i, j in np.nditer([A, B], [], [ro, wo]): # <---- 
    j[()] = i        # <---- 
print('A = {0}'.format(A)) 
print('B = {0}'.format(B)) 
print('{0}, {1}'.format(i, j)) 
관련 문제