import pandas as pd
import numpy as np
import seaborn as sns
'''
<데이터 프레임 만들기 >
원소 3개씩 담고 있는 리스트를 5개 만든다 . 이들 5개의 리스트를 원소로 갖는
딕셔너리를 정의하고, 판다스(DataFrame()) 함수에 전달하면 5개의 열을 갖는
데이터 프레임을 만든다.
이때, 딕셔너리의 키(k)가 열 이름 (c0~c4)가 되고, 값(v)에 해당하는 각 리스트가
데이터 프레임의 열이 된다 . 행 인덱스에는 정수형 위치 인덱스(0,1,2)가 자동지정된다.
'''
#열이름 c0,c1,c2,c3,c4를 key로 하고, [1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15]
#리스트를 value로 갖는 딕셔너리 정의
list_data = {'c0':[1,2,3],
'c1':[4,5,6],
'c2':[7,8,9],
'c3':[10,11,12],
'c4':[13,14,15]}
#데이터 생성시 열 이름을 한정하면 해당 열만 추출
print(pd.DataFrame(list_data,columns = ["c0","c1"]))
print('---------------------------------------------')
#데이터가 존재하지 않는 열을 추가하면 해당 열에는 NaN 값들 추가
print(pd.DataFrame(list_data,columns=['c0','c1','c2','c3','c4','debt']))
'''행 인덱스 / 열 이름 설정
--------------------------------------------------------------------------
'''
df = pd.DataFrame([[15, '남', '덕영중'], [17, '여', '수리중']],
index=['준서', '예은'],
columns=['나이', '성별', '학교'])
#행 인덱스,열 이름 확인하기
print('---------------------------------------------')
print(df.index) # 행 인덱스
print(df.columns) # 열 이름
#속성을 지정하여 변경하기
#데이터 프레임 df의 행 인덱스 배열을 나타내는 df.index와 열 이름 배열을 나타내는
#df.columns에 새로운 배열을 할당하는 방식으로, 행인덱스와 열 이름을 변경할 수 있다.
#행인덱스 변경: DataFrame 객체.index = 새로운 행 인덱스 배열
#열 이름 변경 : DataFrame 객체.columns = 새로운 열 이름 배열
#행 인덱스 준서는 학생1 , 예은은 학생 2로 변경하기
#나이는 연령, 성별은 남녀, 학교는 소속으로 열 이름 변경하기
#데이터 프레임, 행 인덱스 ,열이름 확인하기
'''
rename 메소드
rename()메소드를 적용하면, 행 인덱스 또는 열 이름의 일부를 선택하여 변경 가능.
원본 객체를 변경하려면 , inplace = True 옵션 사용
'''
df.rename(index={'준서':'학생1','예은':'학생2'}, inplace=True)
df.rename(columns={'나이':'연령','성별':'남녀','학교':'소속'},inplace=True)
#Drop메소드를 사용하여 열 삭제
df4 = pd.DataFrame([[15, '남', '덕영중'], [17, '여', '수리중']],
index=['준서', '예은'],
columns=['나이', '성별', '학교'])
'''
loc : 인데스 이름 예 : ['a':'c'] -- > a,b,c
iloc : 정수형 위치 인덱스 예 : [3:7] --> 3,4,5,6
DataFrame() 함수로 데이터 프레임 변환. 변수 df에 저장
'''
exam_data ={'수학':[90,80,70],
'영어':[98,89,95],
'음악':[85,95,100],
'체육':[100,90,90]}
df = pd.DataFrame(exam_data, index=['서준','우현','인아'])
print(df[['수학']]) # 수학 가져오기
print(df.loc[['서준']]) # 키 인덱싱
print(df.iloc[0]) #서준이는 첫번째 이므로, 0
'''원소 선택
-1개의 원소 선택
--'이름'열을 새로운 인덱스로 지정하고, df 객체에 변경사항 반영
--df6 = df.set_index('이름')
--데이터프레임 df6의 특정 원소 1개 선택 ('서준'의 음악점수)
'''
df6 = df.copy() # df 카피
print(df6.loc['서준','음악']) # 서준의 음악 점수 추출
print(df6.iloc[0,2]) # 위치 인덱싱으로 찾기
print(df6.loc['서준',['음악','체육']]) # 서준의 음악 , 체육
print(df6.iloc[0,-2:]) # 서준의 음악 , 체육
print(df6.loc['서준','음악':'체육'])
print(df6.loc[['서준','우현'], ['음악','체육']])
print(df6.iloc[[0,1],[2,3]])
'''
열 추가
추가하려는 열 이름과 데이터 값을 입력 . 마지막 열에 덧붙이듯 새로운 열을 추가
열추가: DataFrame 객체[ '추가하려는 열 이름' ] = 데이터 값
2) 이때 모든 행에 동일한 값이 입력되는 점에 유의
다음 예제에서 국어 열을 새로 추가하는데 , 모든 학생들의 국어 점수가 동일하게 80점
으로 입력되는 과정을 보여준다.
'''
df7 =df.copy()
df7['국어'] = 80
print(df7)
#행 추가
#pd.DataFrame.loc['새로운 행 이름'] = 데이터 값
'''
df 복사본 df8에 새로운 행(row)을 추가 - 같은 원소 값을 입력 (숫자 0 입력)
df8.loc[3] = 0
새로운 행(row)을 추가 - 원소 값 여러개의 배열 입력(동규 90,80,70,60,50 입력)
df8.loc[4] = ['동규',90,80,70,60]
새로운 행 추가 - 기존 행 복사 (기존의 4번째 행)
df8.loc['행5'] = df8.loc[3]
'''
df8 = df.copy()
df8.loc[3] = 0
df8.loc[4] = [90,80,70,60]
df8.loc['행5'] = df8.loc[3]
'''
원소 값 변경
원소를 선택하고 새로운 데이터 값을 지정
원소 값 변경 : DataFrame 객체의 일부분 또는 원소를 선택 = 새로운 값
1개의 원소를 변경
-데이터프레임 df6(이름이 인덱스로 지정된 데이터 프레임)의 특정원소를 반영
-'서준'의 체육점수를 iloc활용 80점으로 변경
-'서준'의 체육점수를 loc 활용 90점으로 변경
-'서준'의 체육점수를 loc[,] 활용 100점으로 변경
'''
df6.loc['서준','체육'] = 90
df6.loc['서준',['음악','체육']] = 90,60
print(df6)
'''행, 열의 위치 바꾸기
데이터 프레임의 행과 열을 서로 맞바꾸는 방법
'''
#가로 세로가 바뀐다.
print(df.transpose())
#특정 열을 행 인덱스로 설정
'''set_index() 메소드를 사용하여 데이터프레임의 특정 열을 행 인덱스로 설정한다.
'''
df = pd.DataFrame(exam_data)
print(df)
'''행 인덱스 재배열 reindex '''
#딕셔너리를 정의
dict_data = {'c0':[1,2,3],
'c1':[4,5,6],
'c2':[7,8,9],
'c3':[10,11,12],
'c4':[13,14,15]}
#딕셔너리를 데이터 프레임 df로 변환 인덱스를 [r0,r1,r2]로 저장
df=pd.DataFrame(dict_data, index=['r0','r1','r2'])
#인덱스를 ['r0','r1','r2','r3','r4']로 재지정하여 ndf에 저장
ndf = df.reindex(['r0','r1','r2','r3','r4'], fill_value =0)
print(ndf)
print(df.reindex(['r2','r1']))
'''행 인덱스 초기화
reset_index() 메소드
-정수형 위치 인덱스로 초기화
-기존 행 인덱스는 열로 이동, 새로운 데이터프레임 객체를 반환
-정수형 위치 인덱스로 초기화: DataFrame 객체.reset_index()
-행 인덱스를 정수형으로 초기화
'''
#제목을 따로 지정하지 않으면 index 형태로 나오게 된다.
ndf = df.reset_index()
print(ndf)
'''행 인덱스 정렬
행 인덱스를 기준으로 데이터프레임 정렬
sort_index() 메소드로 행 인덱스를 기준으로 정렬
ascending 옵션을 사용하여 오름차순 또는 내림차순으로 설정
새롭게 정렬된 데이터프레임 객체를 반환
행 인덱스 기준 정렬 : DataFrame 객체.sort_index()
내림차순으로 행 인덱스 정렬
'''
df.sort_index(ascending=False)
'''특정행을 기준으로 데이터프레임 정렬
sort_values() 메소드로 행의 기준으로 정렬
ascending 옵션을 사용하여 오름차순 또는 내림차순 설정
새롭게 정렬된 데이터프레임 객체를 반환
행 인덱스 기준 정렬 : DataFrame 객체.sort_values()
''''''
시리즈 vs 숫자
시리즈와 숫자 연산 : Series 객체 + 연산자 (+,-,*,/) + 숫자
--딕셔너리 데이터로 판다스 시리즈 만들기
--student1 = pd.Series({'국어':100,'영어':80,'수학':90})
'''
student1 = pd.Series({'국어':100,'영어':80,'수학':90})
print(student1/200)
'''출력:
국어 0.50
영어 0.40
수학 0.45
dtype: float64
'''
'''시리즈 vs. 시리즈
-시리즈와 시리즈 사이에 사칙연산 처리
-같은 인덱스를 가진 원소끼리 계산
-해당 인덱스에 연산 결과를 매칭하여 새 시리즈를 반환
-시리즈와 시리즈 연산: Series1 + 연산자(+,-,*,/) + Series2
--딕셔너리 데이터로 판다스 시리즈 만들기
--student1 = pd.Series({'국어':100,'영어':80,'수학':90})
--student2 = pd.Series({'수학':80,'국어':90,'영어':80})
'''
student1 = pd.Series({'국어':100,'영어':80,'수학':90})
student2 = pd.Series({'수학':80,'국어':90,'영어':80})
#두 학생의 과목별 점수로 사칙연산 수행
addition = student1 + student2 #덧셈
subtraction = student1 - student2 #뺄셈
multiplication = student1 * student2 #곱셈
division = student1 / student2 # 나눗셈
#사칙연산 결과를 데이터프레임으로 합치기 (시리즈 -> 데이터 프레임)
result =pd.DataFrame([addition,subtraction,multiplication,division],
index = ['덧셈','뺄셈','곱셈','나눗셈'])
print(result)
'''
두 시리즈의 원소 개수가 다르거나, 혹은 시리즈의 크기가 같더라도 인덱스 값이 다를 수 있다.
-이런경우, 유효한 값이 존재하지 않는다는 의미로 NaN으로 처리
같은 인덱스가 양쪽에 모두 존재하여 서로 대응되어도 어느 한 쪽의 데이터 값이 NaN인 경우가 있다.
-연산의 대상인 데이터가 존재하지 않기 때문에 NaN으로 처리
'''
#딕셔너리 데이터로 판다스 시리즈 만들기
student1 = pd.Series({'국어':np.nan,'영어':80,'수학':90})
student2 = pd.Series({'수학':80,'국어':90})
'''
<연산 메소드 활용>
-객체 사이에 공통 인덱스가 없는 경우 NaN을 반환
-이런 상황을 피하려면 연산 메소드에 fill_value 옵션 설정
-연산 메소드 사용(시리즈와 시리즈 덧셈): Series1.add(Series2,fill_value=0)
두 학생의 과목별 점수로 사칙연산 수행(연산 메소드 사용)
'''
#add, sub,mul,div
print(student1.add(student2, fill_value=0))
print(student1 + student2)
'''
데이터프레임 연산
-데이터프레임은 여러 시리즈가 한데 모인 것이므로, 시리즈 연산을 확장하는 개념
-먼저 행/열 인덱스를 기준으로 정렬 후 일대일 대응되는 원소끼리 연산
데이터프레임 vs. 숫자
-데이터프레임에 어떤 숫자를 더하면, 모든 원소에 숫자를 더한다. 덧셈 , 뺄셈 , 곱셈,
나눗셈 모두 가능하다.
''''''
타이타닉 데이터 셋
- Seaborn라이브러리에서 제공하는 데이터 셋, 타이타닉호 탑승자에 대한 인적사항과
구조 여부등을 정리한 자료
load_dataset() 함수로 불러오고, Seaborn 내장 데이터셋의 종류는 아래와 같다.
'''
#titanic 데이터셋에서 age,fare 2개 열을 선택하여 데이터프레임 만들기
df = sns.load_dataset('titanic').loc[:,['age','fare']]
#데이터프레임에 숫자 10 더하기
addition = df+10
'''데이터 프레임 + 데이터 프레임 연산
->각 데이터프레임의 같은 행, 같은 열 위치에 있는 원소끼리 계산
->동일한 위치의 원소끼리 계산한 결과값을 원래 위치에 다시 입력하여 데이터프레임을 만든다.
'''
#데이터프레임끼리 연산하기
print(addition - df)