파이썬 transpose - paisseon transpose

벡터, 행렬 연산에 행과 열을 맞추는 것이 매우 중요하다.

T 속성을 통해서 2차원 배열의 전치(transpose) 행과 열을 바꾸는 작업을 진행한다.

NumPy 배열 즉 ndarray 클래스 인스턴스의 T 속성을 이용해 전치행렬을 구한다.

전치행렬이 궁금하다면...

[수학][행렬] 전치행렬

임의의 행렬 A가 주어졌을때 행렬A의 행과 열을 바꾼 행렬을 행렬A의 전치행렬이라 하고 AT 표기한다. 예를들면 2x4 행렬의 전치행렬은 4x2 행렬이 된다. 좀더 쉬운 컨셉으로 설명하면 주대각선을 기준으로 뒤집은..

newprivatemarine.tistory.com

요즘 1학년 수학 수업을 청강하고 있는데

교제에 행렬 덧셈을 직접 코드로 구현한 것이 나왔다.

그래서 numpy의 .T 사용하는 것 대신

행렬 전치도 코드로 구현해 사용하고 싶어서 구현하기로 했다!!

(일주일이 걸릴 줄은 몰랐지만...)

코드는 책에 나온 코드에 구글링해서 나온 코드 참고해서 작성했다.

구글링 없이 짜보려고 노력하다 도오오오저히 안될 것 같아 구글링 해보니까

입력한 배열을 전치하는 코드가 있긴 했지만,

문제는 입력값이 아니라 미리 행렬길이를 정해놓은 코드

입력하는 행렬에 따라 자유롭게 전치하는 것이 불가능했다.

그래서 이 부분을 입력값에 따라 자유롭게 전치가 가능하도록 구현해봤다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

def matrixMult(A):

row=len(A)

col=len(A[0])    

= [[0 for row in range(row)]for col in range(col)]

for i in range(row):

for j in range(col):

B[j][i]=A[i][j]

return B

= [[2-3],[-14]]

matrixMult(A)

cs

끽해봤자 10줄정도 되는 짧은 코드지만

살면서 처음으로 라이브러리에 있는 함수 그대로 안쓰고

직접 코드 짜봤다는 것에 의의를 두면 현타는 그닥 많이 오진 않았다..ㅎㅎ

-암튼 신나서 쓴 코딩 포스팅 끝-

참고

-미적분과 벡터해석 기초, 경문사, 심성아&윤기현

-Program to find transpose of a matrix, GeeksforGeeks

행 열 전환은 데이터프레임이름.transpose()를 하면 전환 할 수 있다. 전환이 되고 난 상태에서 바로 데이터 프레임을 사용하려고 하면 열 이름이 의도치 않게 한 행의 데이터로 되어 있는 것을 볼 수 있을 것이다.

이 때, 데이터프레임이름(columns=데이터프레임이름.iloc[0],inplace=True)데이터프레임이름=데이터프레임이름.drop(데이터프레임이름.index[0])를 해주면 행열 전환을 잘 마무리 할 수 있다.

아래 코드에서 데이터 프레임 이름은 df이다.

DataFrame - 셀의 값을 변경하기, 행과 열 추가하기 & 전치하기

import pandas as pd exam_data = {'이름' : ['서준', '우현', '인아', '영철'], '수학' : [90, 80, 70, 30], '영어' : [98, 89, 95, 22], '음악' : [85, 95, 100, 55], '체육' : [100, 90, 90, 77]} df = pd.Data..

forlater.tistory.com

numpy는 데이터 처리에 엄청난 능력을 보여주는 라이브러리이지만,
작은 규모의 프로그램을 만드는 상황이나, 그리고 매번 실행환경이 달라져야 하는 코드라면,
numpy가 제공하는 함수들을
파이썬 기본 문법으로 해결하고 싶을 때도 생깁니다.
그래서 아주 유용하고 빈번하게 사용되는 전치행렬에 대한 내용을 기본문법으로 구현해 보겠습니다.

전치행렬이 뭔데?

일단 행렬이 뭔지 아시는 것을 가정하고 설명하겠습니다.
행과 열을 뒤바꾸는 것이 전치 행렬인데요.

파이썬 transpose - paisseon transpose

엑셀로 예를 들어보면 이런 식이 되는거죠.

초록색 데이터는 [1, 2, 3, 4, 5] 로 데이터가 묶였지만
붉은색 데이터는 [1, 6]으로 데이터가 묶여 있죠?

파이썬내장 zip 함수로 전치행렬 만들어보기

이차원행렬 = [
    [1,2],
    [3,4],
    [5,6]
]
print(이차원행렬)
[[1, 2], [3, 4], [5, 6]]

위와 같이 이차원 행렬을 하나 준비해봅니다.
(3x2) 크기를 갖는 이차원 행렬이군요.

전치행렬1 = list(zip(*이차원행렬))
print(전치행렬1)
[(1, 3, 5), (2, 4, 6)]

그 다음은 엄청 쉽습니다. zip함수를 통해서 위와 같이 코드를 작성하면 끝인데요.
zip함수가 뭐길래 저렇게 전치행렬이 튀어나오는 걸까요?

zip함수를 좀더 자세히 다루는 포스팅을 하겠지만,
일단 zip 함수가 여러개의 리스트를 순서대로 짝을 맞추어 주는 역할을 한다고 이해하시면 됩니다.
전치행렬이 나오는게 중요하지 zip함수의 원리를 파고드는게 지금 중요하진 않아요.(코드에 있는 별표시도 지금은 신경쓰지 마세요.)

필요한 곳에 계속 사용하다 보면 자연스럽게 zip 함수의 원리를 공부하게 되실 거고,
오늘은 맛보기라 생각하세요.

zip함수 없이 전치행렬 만들기?

전치행렬을 성공적으로 만들었는데, 만약 zip함수를 안쓰고 만들고 싶다면 어떻게 할까요?

## for문 최대원소기준##
전치행렬2 = []
row_num = len(이차원행렬)
col_num = max([len(a) for a in 이차원행렬])

for x in range(col_num):
    tmp = []
    for y in range(row_num):
        try:
            tmp.append(이차원행렬[y][x])
        except:
            tmp.append(0)
    전치행렬2.append(tmp)

전치행렬2
[[1, 3, 5], [2, 4, 6]]

짠, 이렇게 코드를 짜면 됩니다!

그런데 이 코드는 zip 함수를 써서 만드는 전치행렬과는 조금 다르게 구현했는데요.
가끔 필요할 때가 있어서 이렇게 만들었습니다.

어떻게 다르냐고요?

이차원행렬 = [
    [1,2],
    [3,4],
    [5,6,7]
]
print(이차원행렬)
[[1, 2], [3, 4], [5, 6, 7]]

이차원행렬의 구성을 이렇게 바꿔볼게요. 각 행의 원소들 갯수가 다르죠?

전치행렬3 = list(zip(*이차원행렬))
print(전치행렬3)
[(1, 3, 5), (2, 4, 6)]

그런데 zip 함수로 전치행렬을 구해보면 다음과 같이 7이 무시된 채로 행렬이 반환됩니다.
왜냐하면 zip함수는 리스트들의 원소를 하나씩 매칭하는 함수이기 때문에, 작은 원소를 가진 행을 기준으로 전치행렬을 만들기 때문이죠.

그런데 사실 이렇게 되면 가지고 있던 데이터의 일부가 손실되는 꼴이니
사용자의 의도와는 조금 다른 코드가 될 수 있습니다.

## for문 최대원소기준##
전치행렬4 = []
row_num = len(이차원행렬)
col_num = max([len(a) for a in 이차원행렬])

for x in range(col_num):
    tmp = []
    for y in range(row_num):
        try:
            tmp.append(이차원행렬[y][x])
        except:
            tmp.append(0)
    전치행렬4.append(tmp)

전치행렬4
[[1, 3, 5], [2, 4, 6], [0, 0, 7]]

그런데 제가 아까 for문을 사용해서 만든 코드를 실행하면,
짝 지을 원소가 없어서 누락되었던 7도 결과값으로 들어가고, 공석이 될 수 밖에 없는 자리는 0으로 채워져 있죠?

이렇게 최대원소 기준으로 전치행렬을 만들어야 할 상황이 있어서, 코드를 이렇게 짜 본거예요.

이 코드를 함수로 만들어 재사용성을 높혀볼까요?

def 최대전치(이차원행렬):
    전치행렬 = []
    row_num = len(이차원행렬)
    col_num = max([len(a) for a in 이차원행렬])

    for x in range(col_num):
        tmp = []
        for y in range(row_num):
            try:
                tmp.append(이차원행렬[y][x])
            except:
                tmp.append(0)
        전치행렬.append(tmp)

    return 전치행렬

함수로 만들었으니 테스트 해보겠습니다.

전치행렬5 = 최대전치(이차원행렬)
print(전치행렬5)
[[1, 3, 5], [2, 4, 6], [0, 0, 7]]

잘 되는 군요!!! 꼭 한번 따라서 코드를 작성해 보세요!!