5/16 Today I Learned

boks·2024년 5월 16일
post-thumbnail


위는 시리즈타입
아래는 데이터프레임 타입

📖 학습한 내용

  • pandas
  • opeCV

📖 핵심내용

📌 pandas

  • pd.date_range()
date_range

DataFrame 구조 변경하기

  1. 데이터 프레임 슬라이싱
  • 행을 인덱싱으로 슬라이싱 하려면, iloc[] 이용!
df = pd.DataFrame(np.random.randn(10,4))
pieces = [df.iloc[:3], df.iloc[3:7], df.iloc[7:]]

  1. concat()
  • 리스트를 받아서 행방향으로 붙인다. vstack과 유사하다.
a= df.iloc[:3]
b= df.iloc[3:7]
c= df.iloc[7:]

pd.concat([a,b,c])


-> 인덱스 슬라이싱으로 나눠졌던 데이터프레임이 다시 하나로 합쳐졌다.

  1. merge
  • 굳이 표현하면 열방향 붙이기

  • SQL에서 join 과 같은 역할

  • 어떤 값을 기준으로 삼아 두개의 DF를 병합한다.

  • 컬럼 기준 병합

    1) 키 값 기준 - 중복되는 키가 있을때

    left = pd.DataFrame({"key": ["foo", "foo"], "lval": [1, 2]})
    right = pd.DataFrame({"key": ["foo", "foo"], "rval": [4, 5]})
    pd.merge(left, right, on='key')


    -> 키가 foo로 서로 중복되어 있을때, 정확히 어떻게 지정된 것은 없다. 따라서 낼 수 있는 모든 경우가 출력된다.

    2) 키 값 기준 - 중복 되는 키가 없을때
    -> 바로 열방향으로 데이터프레임이 합쳐진다.

    3) 키 갑이 다르지만, 벨류가 같을때
    -> 키1 키2 컬럼이 생기고 그대로 합쳐진다.
    -> pd.merge(left, right, left_on='key1', right_on='key2')

    4) inner join 모두 공통되는 것만 출력
    -> pd.merge(left, right, left_on='lval', right_on='rval', how='inner')
    -> how=inner 디폴트므로 생략가능 pd.merge(left, right, left_on='lval', right_on='rval')

    5) outer join 할 수 있는 값 모두 나타내기
    -> 공통된것이 없어 값이 없는것은 NaN 으로 표현
    -> pd.merge(left, right, left_on='lval', right_on='rval', how='outer')

  1. Grouping
    -> groupby()
    -> 컬럼 별로 그룹을 지어서 의미있는 통계값을 낼 수 있게 한다.
  1. pivot_table
    -> 행이나 열을 자유롭게 바꿔가면서 새로운 데이터프레임을 생성한다.
    -> 중복되어서 하나로 묶이는 값이 있으면 평균으로 표기된다.
  1. 저장하기 / 불러오기
    -> 엑셀 파일로 저장하기 : df.to_excel('test/foo.xlsx', sheet_name='Sheet1')
    -> 엑셀 파일 불러오기 : df = pd.read_excel('test/foo.xlsx')
    -> csv 파일로 저장하기 : df.to_csv('test/foo.csv', encoding='utf-8', index=False)
    -> csv 파일 불러오기 : df = pd.read_csv('test/foo.csv')

📌 openCV

  • 라이브러리 설치 : df = pd.read_csv('test/foo.csv')
  • import cv2

새창으로 이미지 열고 닫기

  • openCV를 사용하여 파일 읽기 : cv2.imread('이미지파일이름및경로')
    -> 배열의 자료형이다.
    -> 이미지는 사실 배열로 이뤄져있어서 배열 성질 사용할 수 있다.
  • 이미지 열고 닫기
cv2.imshow('park', img)  # 경로에 있는 이미지를 창으로 불러오기
cv2.waitKey() # 실제로 이미지 띄우기 + 파일 실행상태에서 아무키나 눌러서 종료

cv2.destroyAllWindows() #  응답없음 방지
  • while 사용하여 특정 키 누를때까지 열기
cv2.imshow('park', img)
while True:
    if cv2.waitKey() ==ord('q'): # 아무키가 아니라 q를 눌러야 다음이 진행 (break 발동)
        break

cv2.destroyAllWindows() 

-> 매우 유용하므로 표현을 알아두자
-> 아스키 코드를 이용하여 스페이스바, esc 키 등을 이용할 수 있다.

  • 이미지 저장 : cv2.imwrite('저장할이미지경로및이름', img)

matplotlib 으로 출력하기

import matplotlib.pyplot as plt
1) pyplot으로 이미지 열기
2) OpenCV에서 이미지를 읽을 때 기본적으로 BGR (파란색, 녹색, 빨간색) 색상 순서로 읽어온다
3) matplotlib은 RGB (빨간색, 녹색, 파란색) 색상 순서를 기대한다.
-> 따라서 OpenCV로 읽은 이미지를 matplotlib으로 표시할 때 색상이 파란색으로 나타나므로 이미지를 RGB 색상 순서로 변환해야한다.

4) 색상 순서 변환 cvtColor
-> cv2.cvtColor(이미지, cv2.COLOR_BGR2RGB)
-> pyplot이 정확히 읽을 수 있게 해준다.

5) 그레이 스케일로 읽기
cv2.imread('imgs/cat.bmp', cv2.IMREAD_GRAYSCALE)
-> 이미지를 플롯할때 matplotlib은 기본적으로 컬러 이미지로 간주하기 때문에 컬러 맵을 지정해야한다
->plt.imshow(gray_img, cmap='gray')
-> 흑백사진은 색상이 들어가지 않으므로 2차원이다. (480,640)

이미지 선택 및 사각형 그리기

1) 흑백 이미지 생성
black_img = np.zeros((480, 680, 3), dtype=np.uint8)
white_img = np.ones((480, 680, 3), dtype=np.uint8) * 255

2) 이미지 부분 선택
-> 결국 이미지도 배열이기에 슬라이싱을 하여 선택할 수 있다.
-> plt.imshow(rgb_img[50:330, 250:550,: ])
-> 객체[높이, 너비, 색체)]

3) 사각형 그리기 rectangle()
-> 대각선 끝을 알면 직사각형 그릴 수 있다
-> 대각선 한점 선택, 나머지 한점 선택, 색상 선택, 선 굵기 선택

rgb_img = cv2.cvtColor(bgr_img, cv2.COLOR_BGR2RGB)
cv2.rectangle(rgb_img, (250, 50), (550,350),(255,0,0),2);
plt.imshow(rgb_img);

영상 밝기 조절을 위한 영상의 덧셈 연산

  • 이미지 밝기도 결국 배열이기 때문에 덧셈 연산을 해주면 전체적으로 밝아진다.
  • 하지만 결국 최댓값이 255이다.
  • 255가 넘어가는 값을 가지면 남은 값만큼 1부터 시작하므로 매우 어둡게 나타난다.
dst2 = src +100
plt.imshow(dst2, cmap='gray'); 

1) cv2.add() 함수 이용하기

  • 원하는 이미지에 전체적으로 원하는만큼 값을 올려서 255가 넘어가면 멈춘다.
dst1 = cv2.add(src,100) # 값에 100을 더해서, 255을 넘어가면 잘라줘
plt.imshow(dst1, cmap='gray')

📖 흥미로운 점 / 새로 알게된 점

  • DataFrame 의 discribe를 하면 통계값들이 나온다.
    이때 값에 nan이있다면 어떻게 될지 궁금했다. nan이 있다면 결과를 nan으로 줄지, 아니면 계산에서 nan을 제외하고 결과를 낼지, 아니면 nan을 0으로 취급하여 결과를 낼지 궁금했다.
    직접 코드를 짜서 해봤다.
import pandas as pd
import numpy as np

data1 = {'A': [1, 2, np.nan, 4, 5],
        'B': [np.nan, 2, 3, 4, 5]}

data2 = {'A': [1, 2, 4, 5],
        'B': [2, 3, 4, 5]}


df1 = pd.DataFrame(data1)
df2 = pd.DataFrame(data2)

print('원래 결과 : ',df1.describe())
print()
print('0으로 대체한 결과 : ',df1.fillna(0).describe())
print()
print('nan을 제외한 결과 : ',df2.describe())

-> 원래 결과가 0을 제외한 결과와 일치하므로, describe() 함수는 nan을 계산에서 제외하고 통계값을 낸다는 것을 알 수 있다.

📖 어려운 부분

  • merge 개념이 직관적이지 않아서 해보면서 배워야했다. 이론적으로는 알지만 아직도 헷갈린다. 원하는 결과를 뽑아내기 위해서 적기가 까다로울 것 같다. 익숙하지 않고, 배운게 아직 정리가 되질 않아서 그런 것 같다. 몇번 더 사용해보고, 며칠 지나고 다시보면 쉽게 이해될 것 같다.

📖 이후 학습 계획

  • 내일은 통계특강이 있다. 기초 통계에 대해 공부할 생각이다.

📖 기타

  • 이미지 관련하여 마지막 프로젝트를 하기 때문에 matplotlib과 openCV 강의를 좀 기대했다. 하지만 시간이 모자라서 훑고만 지난 것 같다. 이후에 더 디테일하게 배울 시간이 있으니 조급해말고 천천히 하나씩 배워가야겠다.
    통계에 대해서 책으로 공부를 해왔다. 책에서는 이런게 있다 저런게 있다 소개만 하고 넘어가서 답답한 부분이 있었는데, 내일 해소하길 기대한다. 물론 기초 통계만 배우기에 많은 기대를 하기 어려워 보인다. 그래도 그간 독학한 내용을 정리할 좋은 기회라고 생각한다.
profile
설계엔지니어의 변신

0개의 댓글