연랩

[Microsoft AI School 6기] 12/30(9일차) 정리 - 달 탐사, 유성우 본문

MS AI school 6기

[Microsoft AI School 6기] 12/30(9일차) 정리 - 달 탐사, 유성우

parkjiyon7 2024. 12. 30. 17:57

파이썬 데이터 분석

 

아르테미스 달탐사

- OverTheMoon_달탐사

 

목표: 어떠한 암석을 얼마만큼 가져와야 하는가(기존의 암석 수집량과 사용량을 바탕으로)

 

 

데이터의 자료형

 

개별 컬럼은 정수, 실수, 문자, 날짜 등의 자료형(data type)을 가진다

  • object: 문자 또는 문자열(' '으로 구분)
  • int64: 정수
  • float64: 실수
  • datetime64: 날짜(' '으로 구분)
  • boolean: 참/거짓

 

 

데이터 컬럼 살펴보기

 

rock_samples 종류

 

ID: NASA에서 샘플을 추적하는데 사용하는 고유 ID

Mission: 샘플이 수집된 아폴로 임무

Type: 암석 샘플 종류

Subtype: 구체적인 암석 샘플 종류

Weight (g): 암선 샘플 질량 (g)

Pristine(%) : 남아 있는 암석 샘플 백분율

 

위의 info를 보면 Subtype에 null값이 있음을 알 수 있다. pandas에서 isnull()을 사용하면 다음과 같다

 

isnull()

 

데이터의 양이 너무 많아 어디가 null값인지 확인하기 어려움으로 isnull.sum()으로 null값의 위치를 확인할 수 있다,

 

isnull.sum()

 

 

데이터 전처리

 

weight(g) -> weight(kg)

g단위의 칼럼을 kg 단위로 바꾸기 위해서는 value에 0.001을 곱하고, col명을 weight(kg)으로 바꾸어 주어야 한다.

 

1) 칼럼값 변환

칼럼에 변환을 적용하기

df.apply(함수명)

- 데이터프레임의 칼럼, 시리즈 또는 데이터프레임 전체에 대해 함수를 적용

 

apply(함수명)

 

rock_samples['Weight (g)']*0.001 를 적용해도 같은 값이 나온다.

둘 중 무엇으로 연산을 하여도 변수에 적용을 따로 해주어야 한다. 그후, 확인을 하면 다음과 같다

 

변경된 값 적용

 

2) 칼럼명 변환

df.rename(columns = {변경전 컬럼명 : 변경후 컬럼명}, inplace = True)

복수 개의 column 명을 변경할 수 있다

 

이때, inplace = True를 적용하기 전에 미리 확인을 하고 옵션을 적용하는 것을 추천한다

 

rename

 

혹은 다음을 통해서도 변경이 가능하다

df.columns = ['ID', 'Mission', 'Type', 'Subtype', 'Weight (kg) ', 'Pristine (%)']

 

Mission 별로 암석의 중량을 분리하여 살펴보자

이를 위해서 우선, 어떤 mission들이 있는 지 살펴보아야 한다

 

unique()

 

또한 value_counts를 통해 임무 별로 가져온 암석의 양을 알 수 있다

 

value_counts()

 

missions라는 새로운 데이터 프레임을 만들어 각 임무 별 정보를 저장하기 위해 missions에 'Mission' 칼럼을 만들고 각 임무를 넣은 칼럼은 다음과 같다

 

missions DataFrame 새로 만들기

 

3) 그룹핑

rock_samples에서 각 미션별로 중량을 살펴보기 위해서 groupby()를 사용할 수 있다.

 

groupby()

 

위의 사진에서 보면, 중량을 Mission 단위(그룹)으로 묶어서 출력하였음을 알 수 있다. 이를 sample_total_weight에 저장하고 이를 missions 데이터 프레임에 결합하여 보자

 

4) 데이터프레임과 시리즈 연결

pd.merge(df, s, on = '시리즈 인덱스와 같은 데이터프레임의 컬럼명')

병합을 할 때에는 기준이 있어야 한다. 그 기준을 on ' ' 에 지정하여 주면 된다.

데이터프레임과 데이터프레임도 연결이 가능하다.(df+df, s+s, s+df 가능)

JOIN이라고 이해하면 된다...

 

merge()

 

sample_total_weight.values를 하면 해당 값을 불러올 수 있기 때문에 이를 이용하여 missions 데이터 프레임에 값을 추가하는 방법도 존재한다.

Weight (kg)의 컬럼명을 Sample weight (kg)으로 변경하면 다음과 같다

 

rename()

 

다음으로 임무 간 중량 차이를 구해보도록 하자

 

5) column에서 각 값 별 차이

diff()

 

diff()

 

임무 별로 가져온 암석의 중의 차이를 비교 하기 위해 diff()를 사용하였다. 이때, 맨 위에 NaN이 존재하는 이유는 그 전 값이 없어 차이를 구할 수 없기 때문이다. 이를 missions에 추가하면 다음과 같다

 

diff()

 

6)결측치 0으로 채우기

Apollo11은 이전 값이 없으므로 '0'으로 값을 채우도록 한다.

 

fillna()

 

missions = missions.fillna(0)로도 결측값을 0으로 채울 수 있다.

 

 

달 탐사선 중량 데이터 추가

 

NASA - NSSDCA - Master Catalog - Spacecraft Query

 

Apoolo 달탐사 임무에 사용된 Saturn V 로켓에는 두 가지 모듈이 있다

 

승무원 영역(Crewed Area)

 

달 모듈(Lunar Module):

- 달 궤도에 도달한 후 명령 모듈에서 분리

- 달 표면에 착륙

- 우주 비행사 수송

- 우주 비행사는 달에서 수집된 암석 샘플을 여기에 싣고 명령 모듈로 귀환

 

명령 모듈(Command Module):

- 우주 비행사가 생활하는 모듈

- 우주비행사와 수집된 암석 샘플이 이 모듈에 실려 지구로 귀환

 

이러한 모듈의 무게를 고려해야한다. 즉, 아폴로 임무별로 달 모듈과 명령 모듈의 정보를 추가해야 달 탐사선을 위한 정확한 중량 계산이 가능하다

따라서 missions 데이터프레임에 각 모듈의 이름, 중량, 중량 차이에 관한 칼럼을 추가할 예정이다

 

Luna module 정보 추가

 

1) Luna module 이름과 중량 정보 추가

우선 달모듈이름과 달모듈중량 column을 추가하면 다음과 같다

 

달 모듈 정보 추가

 

2) Luna module 중량 차이(아폴로 임무별)

 

diff()를 사용하여 아폴로 임무별로 달 모듈 중량 차이를 구해서 데이터 프레임에 추가하면 다음과 같다

diff()

 

여기에서 발생한 결측치를 0으로 채우면 다음과 같다

 

fillna()

 

Command Module 정보 추가

 

Luna module에서 수행한 것과 마찬가지로 Command module에서 수행하면 다음과 같다

 

1) Command module 이름과 중량 정보 추가

Command Module 정보 추가

 

2) Command module 중량 차이(아폴로 임무별)

 

diff()

 

fillna()

 

Crewed Area(승무원 영역)

승무원 영역은 달 모듈과 명령 모듈을 합친 영역이다.

 

1) 달 모듈과 명령 모듈 중량을 합한 값을 새로운 칼럼으로 만들어 missions 데이터 프레임에 추가

달 모듈과 명령 모듈 중량을 합한 값을 'Total Weight (kg)'라는 새로운 칼럼으로 생성하여 missions에 추가하면 다음과 같다

 

Crewed Area 정보

 

2) Crewed Area(Total weigth (kg)) 중량 차이(아폴로 임무별)

앞선 절차와 마찬가지로 diff를 구하면 다음과 같다

 

diff()

 

결측값을 0으로 채우면 다음과 같다

 

fillna()

 

각 영역에 대한 정보를 구한 것을 토대로 여러가지 비율을 구해보도록 한다.

비교할 값/기준이 되는 값

 

페이로드에서 승무원 영역이 차지하는 비율

 

페이로드에서 승무원 영역이 차지하는 비율

 

 

승무원 영역에서 암석 샘플이 차지하는 비율

 

승무원 영역에서 암석 샘플이 차지하는 비율

 

페이로드에서 샘플이 차지하는 비율

 

페이로드에서 샘플이 차지하는 비율

 

artemis_mission 데이터프레임 만들기

 

딕녀너리로 데이터프레임 만들기

 

artemis_mission 데이터프레임

 

missions 데이터프레임에서  'Crewed area : Payload', 'Sample : Crewed area', 'Sample : payload' 의 평균값을 구해보면 다음과 같다

 

'Crewed area : Payload', 'Sample : Crewed area', 'Sample : payload' 의 평균값

 

데이터프레임에 Sample weight from total (kg)' 컬럼과 .Sample weight from payload (kg)' 컬럼을 추가한다. artemis_mission['Sample weight from total (kg)'] = artemis_mission['Total weight (kg)']*Sample_CrewedArea_ratio와 

artemis_mission['Sample weight from payload (kg)'] = artemis_mission['Payload (kg)']*Sample_Payload_ratio를 써서 계산하며, 이 둘의 평균을 계산한 칼럼 또한 추가하면 다음과 같다

 

가져와야할 것으로 예측되는 무게에 관한 칼럼을 추가

 

 

아르테미스 임무에서 가져올 암석 종류 구하기

 

Weight에 Pristine을 곱해 데이터프레임에 암석 샘플의 남은 양을 나타내는 칼럼 추가

 

암석 샘플의 남은 양을 나타내는 칼럼 추가

 

수치 데이터의 통계를 살펴보면 다음과 같다

 

요약

 

암석의 평균 무게가 0.16임을 통계를 통해 알 수 있다.

우선, 암석 중 0.16보다 Weight가 큰 샘플을 우선 추출해보도록 하자

 

Weight >=0.16

 

다음으로, weight가 0.16보다 크면서 pristine이 50보다 작은 암석을 찾아보도록 하자

즉, 큰 양을 채취했으나 남은 양이 적은 물질을 필터링 해보았다

Weight >=0.16 & Pristine <= 50

 

이러한 조건을 만족시키는 데이터를 모아 데이터 프레임을 만들면 다음과 같다

 

Low_samples

 

low_samples = rock_samples.loc[(rock_samples['Weight (kg)'] >= 0.16) & (rock_samples['Pristine (%)'] <= 50)] 이와 같이 loc를 사용하여 추출하는 코드 또한 사용할 수 있다.

info를 통해 확인하면 기준을 만족하는 데이터가 27개 남아있음을 확인할 수 있다

 

info

 

이를 Type 별로 살펴 보면 다음과 같다

 

value_counts

 

Basalt와 Breccia의 샘플이 가장 부족함을 알 수 있다.

이를 바탕으로 low_samples의 Type이 Basalt이거나 Breccia인지 확인하기 위해서는 

isin()

을 사용하는 방법이 있다.

 

isin()안에는 iterable이 올 수 있다.

isin()

 

이를 활용하여 low_samples['Type'] 의 값이 'Basalt'이거나 'Breccia'인 행만 추출해서 needed_samples 데이터프레임을 만들면 다음과 같다

 

needed_samples

 

rock_samples 데이터프레임에서 'Type'으로 groupby 해서 암석 샘플의 중량의 합을 구한다. 즉, 아폴로 임무에서 처음부터 수집이 안된 암석을 구한다.

 

groupby()

 

해당 자료를 통해 Crustal과 같은 경우 채취량 자체가 적었음을 확인할 수 있다. 즉, 희귀성이 높다고 볼 수 있으므로 채취할 암석 목록에 포함시키는 방안을 고려할 수 있다

 

따라서 needed_samples에 crustal을 추가하기로 한다.

concat()

디폴트 값은 axis=0이다

concat([df1, df2])

concat

 

아르테미스 임무에 전달할 최종 데이터프레임 needed_samples_overview를 만든다

해당 데이터 프레임에는 어떤 암석을 가져와야하는 지와 얼마만큼 가져와야 하는 지를 기록한다

 

needed_samples_weight

 

needed_samples_weight에는 암석의 무게가 들어있다. needed_samples_weight와 needed_samples_overview를 병합하면 다음과 같다(데이터프레임끼리의 병합)

 

merge

 

merge는 여러번 할 경우 오류가 날 수 있기 때문에 유의해야한다

needed_samples 데이터프레임에서 암석 유형별 중량의 평균을 구하고 needed_samples_overview랑 결합한다

 

avg merge

 

또한 데이터프레임에서 암석 유형별 개수를 구해서 merge한다

 

Type 개수 merge

 

그후, 암석유형별로 차지하는 비율을 구해서 'Percentage of rocks'라는 칼럼에 할당하고 이를 artemis_mission의 Estimated sample weight에 곱해 구해야하는 암석의 중량을 구한다. 이를 평균 무게로 나누어 암석의 개수를 구하여 저장하면 다음과 같은 결론을 구할 수 있다.

 

수집할 암석의 개수

 

 

 

아르테미스 달탐사

- OverTheMoon_유성우

 

- 유성우는 관측자의 위치, 관측 시기, 관측 날짜의 달의 위상 등에 따라 유성우를 볼 수 있는 지의 여부가 달라진다

 

4개의 혜성에서 발생하는 주요 5대 유성우

데처 혜성(Coment Thather) -> Lyids(거문고자리 유성우)

헬리 혜성(Comet Halley) -> Eta Aquaris(에타 물병자리 유성우), Orionids(오리온자리 유성우)

스위프트-터틀 혜성(Comet Swift-Tuttle) -> Perseids(페르세우스 자리 유성우)

템플-터틀 혜성(Comet Tempel-Tuttle) -> Leonids(사자자리 유성우)

 

유성을 관측을 위해서는 각 유성우가 발생하는 기간과 복사점의 별자리 정보 필요

- 달이 너무 밝은 날에는 유성우 관측이 힘들다

 

 

필요한 데이터 정의

 

유성우 데이터 - 관측기간

  • 유성우 이름
  • 시작일
  • 종료일
  • 복사점(별자리)

별자리 데이터 - 관측 가능한 위치

  • 시작위도
  • 종료위도

도시데이터 - 관측자의 위치

  • 도시명
  • 위도

달의 위상 데이터 - 관측조건

  • 날짜
  • 달의 위상

 

 

데이터 파일

 

meteorshowers.csv

moonphases.csv

constellations.csv

cities.csv

 

의 파일 사용, 해당 파일들을 깃허브에 저장되어 있음

 

데이터 분석

 

meteorshowers 데이터를 살펴보면 다음과 같다

 

metor_showers

 

이를 살펴보면 월의 이름이 문자형으로 되어 있는 데, 이를 다루기 위해 숫자로 바꾸는 작업이 필요하다. 이는 dictionary를 사용하여 할 수 있다. 또한 map 함수를 사용할 수 있다.

 

월 변경

 

이때, 두번 map하면 NaN이 뜨게 되므로 유의하여야 한다

마찬가지로 다른 데이터의 월명도 숫자로 바꿔준다.

 

Datetime 형식으로 변환

 

일자 정보를 Datetime 형식으로 변환한다. startmonth, startday 두 칼럼의 데이터를 이용하여 Datetime 형식으로 만들어야 한다.(2020데이터이므로 년도는 2020으로 고정)

-> 8자리 날짜 포맷으로 만들어야 함

ex) 2020*10000  +  11*100  +  6*1  => 20201106

format = '%Y%m%d' ----> 2020-04-28 

 

pd.to_datetime(숫자, format = '%Y%m%d' )

 

datetime

 

meteor_showers에 startdate와 enddate 칼럼을 추가하고 info()를 확인하면 다음과 같다

 

datetime

 

데이터 타입이 datetime으로 되어 있음을 알 수 있다.
마찬가지로 moon_phase 데이터도 변경하여 준다

 

moon_phase에서 달의 위상 데이터를 숫자로 변환

- 반달은 상현과 하현이 광량이 같으므로 0.5로 동일하게 취급한다. 

 

moonphase

 

불필요한 칼럼 삭제

데이터프레임.drop([칼럼이름들........], axis = 1)

칼럼을 삭제하고 싶은 경우, axis = 1

row를 삭제하고 싶은 경우 axis = 0를 하면 된다

 

 

오늘의 간단한 후기

 

데이터 분석을 처음해보는 것이라 익숙치 않아서 쉽지 않았다. 또한 달탐사 파일을 날려먹어서 속상했다...ㅠㅠ 복구 해놓긴 했지만 아까운 마음을 지울 수 없다... 앞으로 백업을 잘 해놓아야 겠다. 데이터 분석을 R에서만 해보았는 데 파이썬의 문법과 같이 사용할 수 있어 기능이 더 많은 거 같았다. 사실 달탐사에서 무엇을 하고 있는 지 길을 잃어서 혼란스러웠다. 데이터 분석을 할 때에는 목표를 확실히 정하고 따라하는 것이 중요할 것 같다.

 

 

 

출처

 

[1] NASA, "Spacecraft query form," NASA Space Science Data Coordinated Archive (NSSDC), 2024. Available: https://nssdc.gsfc.nasa.gov/nmc/SpacecraftQuery.jsp. Accessed: Dec. 18, 2024.4

[2] Time and Date AS, "Moon phases data (CSV)," Timeanddate.com, 2024. Available: https://www.timeanddate.com/moon/phases/. Accessed: Dec. 18, 2024.

[3] NASA, "Meteor showers data (CSV)," NASA Science: Solar System Exploration, 2024. Available: https://solarsystem.nasa.gov/meteor-shower-calendar/. Accessed: Dec. 18, 2024.

 

-If any problem for references, or any questions please contact me by comments.

-This content is only for recording my studies and personal profiles

 

일부 출처는 사진 내에 표기되어 있습니다

본문의 내용은 학습과 개인 profile 이외의 다른 목적이 없습니다

출처 관련 문제 있을 시 말씀 부탁드립니다

상업적인 용도로 사용하는 것을 금합니다

본문의 내용을 Elixirr 강의자료 내용(인선미 강사님)을 기반으로 제작되었습니다

깃허브 소스코드의 내용을 담고 있습니다

본문의 내용은 MS AI School 6기의 강의 자료 및 수업 내용을 담고 있습니다.

 

반응형