본문 바로가기

대학원 공부 및 생활

[python] list~matplotlib 기초 코드

320x100

공부하면서 요약본으로 만든 코드들인데

시험공부할때 쭉 보시면 좋을것 같아요.

 

다만...요샌 바이브 코딩이 대세라..

코드를 이해하는데 중심을 두고 보시면 좋을것 같아요.

시험은 별개인거 아시죠..암기암기...!!

 

# -------------------------------------------
# LIST
# -------------------------------------------
list.append('1') #1개 입력값에 1개 요소 단위로 추가 
 - [1,2] => [1,2]
list.append([3,4,5]) 
 - [1,2] => [1,2,[3,4,5]] # nested한구조가 됨

list.extend([1,2,4]) #1개 입력값에 여러개의 요소 단위로 추가 
 - [1,2] => [1,2,1,2,4]

list.extend(1,2,3) # 오류
list.insert(1,3)   # (index, element)

odd[2:2] = [0,0] # 값 추가 2번 인덱스에 해당 요소추가
odd[2:3] = [5,7] # 값 대체

del list[0]
del list[1:5]

list.remove('p') # 실제값, 중복값 모두제거
list.pop(1)      # index기반 삭제
list.pop()       # 기본값으로 맨뒤 아이템 제거
list.clear()     # 리스트 초기화

list.index('x') # 인덱스 번호 리턴
list.count(2)   # 2값을 가지는 요소수를 반환

list.reverse()          # 리스트 자체를 역으로 정렬
list.sort()             # 기본적으로 오름차순(ascending order)
list.sort(reverse=True) # 내림차순 정렬
list.sort(key=len)      # 글자길이기준 정렬

n_list = sorted(list, reverser=True) #정렬해서 새로운 리스트에 넣어줌
n_list = list[::-1]     # 슬라이싱해서 정렬해서 새로운 리스트에 넣어줘야함

sorted(dictionary)                          # 딕셔너리에서 키값만 정렬후 반환
sorted(dict, reverse =True)
sorted(dict.items(), key = lambda x : x[1]) # 딕셔너리 값기준 items():키와값 모두반환

nlist = list.copy() # 얕은복사로 list = nlist는 같은 내부객체를 사용함,nlist변경하면 list도 변경됨, numpy arr에서는 동일한 명령어가 깊은 복사에 해당됨

# -------------------------------------------
# LIST comprehension
# -------------------------------------------
[expression for item in iterable if condition]

list_comp = [2**x for x in range(10)]
list_comp = [2**x for x in range(10) if x<=8]             # 입력값 필터
list_comp = [2**x if 2**x <=8 else -1 for x in range(10)] # 출력값 필터(반드시 else처리해야함)

## set{} 도 Comprehension가능, 자동중복제거도 가능

print("p" in list)  # 리스트 내 요소 존재여부 => T/F반환
print("p" not in list)


# -------------------------------------------
# Tuple () 슬라이싱은 리스트와 같음, 요소단위로 지우고,수정이 기본적으로 안됨, 자체는 삭제가능
# -------------------------------------------
tuple = ('apple',1,'dog')
a,b,c = tuple                      # unpack시 a,b,c값이  튜플의 각요소 값이 매칭됨
tuple = ('apple',1,'dog',[1,2,3])  # 튜플내 리스트요소는 변경가능
tuple[3][1]=4

del tuple    # 가능
del tuple[1] # 오류


# -------------------------------------------
# Set {} 중복제거
# -------------------------------------------
n_set = set([1,2,4])      # 리스트로 set 만들수 있음
n_set.add(2)              # 추가
n_set.update([2,3,4,5])   # 추가
n_set.discard(6)          # 없는원소제거시 에러없음
n_set.remove(6)           # keyerror

A ={1,2,3} B = {2,3,4}
A|B = A.union(B) = B.union(A)              # 합집합
A&B = A.intersection(B)= B.intersection(A) # 교집합
A-B = A.difference(B)                      # 차집합


# -------------------------------------------
# Dictionary
# -------------------------------------------
dict = ['name':'jack', 'age' : 25]
dict.get('age')
dict['age']
dict['address'] = "downtown"    # 신규값 입력
dict.pop(key값)
dict.popitem()                  # (key, value) 쌍을 제거하고 반환
dict.clear()                    # 초기화
del dict                        # 딕셔너리 자체제거

sorted(dictionary)                          # 딕셔너리에서 키값만 정렬후 반환
sorted(dict, reverse =True)
sorted(dict.items(), key = lambda x : x[1]) # 딕셔너리 값기준 items():키와값 모두반환


# -------------------------------------------
# NUMPY
# -------------------------------------------
# list와 달리 같은 종류의 타입의 데이터로 구성

arr = np.empty(5) # 5개요소로 랜덤값 배열 생성
arr = np.empty([3,4])
arr = np.zeros(5)
arr = np.zeros([2,2]) # 2x2 행렬 생성
arr = np.zeros(5, dtype=np.int32)
arr = np.ones(5)
arr = np.ones([2,2]) #2x2 행렬 생성
arr = np.full(5,7) # 5개 요소에 7값으로 넣어라
arr = np.full([3,4],7)
arr = np.random.random(5) #1차원
arr = np.random.random((3,4)) #2차원 입령르 튜플이나 리스트 모두 받음
arr = np.random.random([3,4]) #2차원
arr = np.random.random((3,4,5)) #3차원 (5열의 4행 )의 3행

arr = np.arange(5)          # (0~5)의 배열생성
arr = np.arange(10,20,2)    # start,stop,step =>10,12,14,16,18


1차원 [1,2,3]                                     # 백터
2차원 [[1,2,3], [4,5,6]]                          # 행렬
3차원 [[[1,2,3], [4,5,6]],[[1,2,3], [4,5,6]]]     # 2X2X3행렬

arr.ndim  # 차원확인
arr.shape # 구조보기

arr_cp = arr         # 얕은 복사 원본을 공유해 하나 수정시 모두 수정됨 
arr_cp = arr.copy()  # 깊은 복사 원본를 서로 공유하지 않고 진정한 복사


# Arithmetic Operation 산술연산자
a+b , a-b , a*b, a/b , a+10 # 각 배열 요소별로 산술적 계산이 이뤄짐

# Array reshaping (차원변화시팀)
arr = np.array([1,2,3,4,5,6])  #1차원
arr2 = np.reshape(arr, (2,3))  #2차원 <=reshape해줌

# Array Slicing
arr = np.array([[1,2,3,4],[4,5,6,7],[7,8,9,1]]) #3x3행렬
arr[:2,:3] # 행과 열로 슬라이싱 지정 [[1,2,3].[4,5,6]]
arr[: , 0] # [1,4,7]
arr[0, :] = arr[0]

# Array Join 1차원
a = np.array([1,2,3]) 
b = np.array([4,5,6])
arr = np.concatenate([a,b]) # 배열합치기 list는 "+"연산자로 합쳐짐
 ㄴ 결과 [1,2,3,4,5,6]
# Array Join 2차원
a = np.array([[1,2,3],[4,5,6]])  #2x3행렬
arr = np.concatenate([a,a]) # 기본값이 axis = 0 행을 의미 행으로 더해라
# -------------------------------------------
# LIST
# -------------------------------------------
list.append('1') #1개 입력값에 1개 요소 단위로 추가 
 - [1,2] => [1,2]
list.append([3,4,5]) 
 - [1,2] => [1,2,[3,4,5]] # nested한구조가 됨

list.extend([1,2,4]) #1개 입력값에 여러개의 요소 단위로 추가 
 - [1,2] => [1,2,1,2,4]

list.extend(1,2,3) # 오류
list.insert(1,3)   # (index, element)

odd[2:2] = [0,0] # 값 추가 2번 인덱스에 해당 요소추가
odd[2:3] = [5,7] # 값 대체

del list[0]
del list[1:5]

list.remove('p') # 실제값, 중복값 모두제거
list.pop(1)      # index기반 삭제
list.pop()       # 기본값으로 맨뒤 아이템 제거
list.clear()     # 리스트 초기화

list.index('x') # 인덱스 번호 리턴
list.count(2)   # 2값을 가지는 요소수를 반환

list.reverse()          # 리스트 자체를 역으로 정렬
list.sort()             # 기본적으로 오름차순(ascending order)
list.sort(reverse=True) # 내림차순 정렬
list.sort(key=len)      # 글자길이기준 정렬

n_list = sorted(list, reverser=True) #정렬해서 새로운 리스트에 넣어줌
n_list = list[::-1]     # 슬라이싱해서 정렬해서 새로운 리스트에 넣어줘야함

sorted(dictionary)                          # 딕셔너리에서 키값만 정렬후 반환
sorted(dict, reverse =True)
sorted(dict.items(), key = lambda x : x[1]) # 딕셔너리 값기준 items():키와값 모두반환

nlist = list.copy() # 얕은복사로 list = nlist는 같은 내부객체를 사용함,nlist변경하면 list도 변경됨, numpy arr에서는 동일한 명령어가 깊은 복사에 해당됨

# -------------------------------------------
# LIST comprehension
# -------------------------------------------
[expression for item in iterable if condition]

list_comp = [2**x for x in range(10)]
list_comp = [2**x for x in range(10) if x<=8]             # 입력값 필터
list_comp = [2**x if 2**x <=8 else -1 for x in range(10)] # 출력값 필터(반드시 else처리해야함)

## set{} 도 Comprehension가능, 자동중복제거도 가능

print("p" in list)  # 리스트 내 요소 존재여부 => T/F반환
print("p" not in list)


# -------------------------------------------
# Tuple () 슬라이싱은 리스트와 같음, 요소단위로 지우고,수정이 기본적으로 안됨, 자체는 삭제가능
# -------------------------------------------
tuple = ('apple',1,'dog')
a,b,c = tuple                      # unpack시 a,b,c값이  튜플의 각요소 값이 매칭됨
tuple = ('apple',1,'dog',[1,2,3])  # 튜플내 리스트요소는 변경가능
tuple[3][1]=4

del tuple    # 가능
del tuple[1] # 오류


# -------------------------------------------
# Set {} 중복제거
# -------------------------------------------
n_set = set([1,2,4])      # 리스트로 set 만들수 있음
n_set.add(2)              # 추가
n_set.update([2,3,4,5])   # 추가
n_set.discard(6)          # 없는원소제거시 에러없음
n_set.remove(6)           # keyerror

A ={1,2,3} B = {2,3,4}
A|B = A.union(B) = B.union(A)              # 합집합
A&B = A.intersection(B)= B.intersection(A) # 교집합
A-B = A.difference(B)                      # 차집합


# -------------------------------------------
# Dictionary
# -------------------------------------------
dict = ['name':'jack', 'age' : 25]
dict.get('age')
dict['age']
dict['address'] = "downtown"    # 신규값 입력
dict.pop(key값)
dict.popitem()                  # (key, value) 쌍을 제거하고 반환
dict.clear()                    # 초기화
del dict                        # 딕셔너리 자체제거

sorted(dictionary)                          # 딕셔너리에서 키값만 정렬후 반환
sorted(dict, reverse =True)
sorted(dict.items(), key = lambda x : x[1]) # 딕셔너리 값기준 items():키와값 모두반환


# -------------------------------------------
# NUMPY
# -------------------------------------------
# list와 달리 같은 종류의 타입의 데이터로 구성

arr = np.empty(5) # 5개요소로 랜덤값 배열 생성
arr = np.empty([3,4])
arr = np.zeros(5)
arr = np.zeros([2,2]) # 2x2 행렬 생성
arr = np.zeros(5, dtype=np.int32)
arr = np.ones(5)
arr = np.ones([2,2]) #2x2 행렬 생성
arr = np.full(5,7) # 5개 요소에 7값으로 넣어라
arr = np.full([3,4],7)
arr = np.random.random(5) #1차원
arr = np.random.random((3,4)) #2차원 입령르 튜플이나 리스트 모두 받음
arr = np.random.random([3,4]) #2차원
arr = np.random.random((3,4,5)) #3차원 (5열의 4행 )의 3행

arr = np.arange(5)          # (0~5)의 배열생성
arr = np.arange(10,20,2)    # start,stop,step =>10,12,14,16,18


1차원 [1,2,3]                                     # 백터
2차원 [[1,2,3], [4,5,6]]                          # 행렬
3차원 [[[1,2,3], [4,5,6]],[[1,2,3], [4,5,6]]]     # 2X2X3행렬

# 차원확인
arr.ndim  # 배열 차원확인

# 구조확인
arr.shape # 구조보기

# 전체 element수구하기
arr.size

# copy차이점 : list와는 반대개념
arr_cp = arr         # 얕은 복사 원본을 공유해 하나 수정시 모두 수정됨 
arr_cp = arr.copy()  # 깊은 복사 원본를 서로 공유하지 않고 진정한 복사


# Arithmetic Operation 산술연산자
a+b  <= np.add(a,b)
a-b  <= np.subtract(a,b)
a*b  <= np.multiply(a,b)
a/b  <= np.divide(a,b)
a+10 # 각 배열 요소별로 산술적 계산이 이뤄짐

# Logical operator 논리연산자
arr = np.array([[1,2,3],[4,5,6]])
arr2 = arr > 2 # True/False값을로 각 요소값 반환

# 전치행렬 : 행x열 => 열x행
arr.transpose()
arr.T

# Array reshaping (차원변화시팀)
arr = np.array([1,2,3,4,5,6])  #1차원
arr2 = np.reshape(arr, (2,3))  #2차원 <=reshape해줌
arr = np.arange(12).reshape(3,4)

# Array Slicing
arr = np.array([[1,2,3,4],[4,5,6,7],[7,8,9,1]]) #3x3행렬
arr[:2,:3] # 행과 열로 슬라이싱 지정 [[1,2,3].[4,5,6]]
arr[: , 0] # [1,4,7]
arr[0, :] = arr[0]

# Array Join 1차원
a = np.array([1,2,3]) 
b = np.array([4,5,6])
arr = np.concatenate([a,b]) # 배열합치기 list는 "+"연산자로 합쳐짐
 ㄴ 결과 [1,2,3,4,5,6]

# Array Join 2차원
a = np.array([[1,2,3],[4,5,6]])  #2x3행렬
arr = np.concatenate([a,a]) # 기본값이 axis = 0 행을 의미 행으로 더해라 (4 x 3)
 ㄴ array([[1, 2, 3], [4, 5, 6], [1, 2, 3],[4, 5, 6]])

arr = np.concatenate([a,a], axis = 1) #axis =1 열을 의미 열방향으로 더해라(2 x 6)
 ㄴ arrry([[1,2,3,1,2,3],[4,5,6,4,5,6]])

x = np.array([1,2]) y = np.array([99],[99])
A = np.array([[7,5],[1,6]])
np.vstack([x,A]) # 행의 방향으로 쌓기 array([[1,2],[7,5],[1,6]]) (1x2) vstack (2x2)=(3x2)
np.hstack([A,y]) # axis = 1과 동일한 동작 np.concatenate([A,y], axis=1)

# Sorting
arr.sort() #원본 수정
n_arr = np.sort(arr) #정렬된 새로운 배열 반환후 저장
n_arr = np.sort(arr, axix = 0) #행의 방향으로 위/아래로 정렬시킴
## [[3,2,4],[5,0,1]] ==> [[3,0,1],[5,2,4]]
n_arr = arr[::-1] #역/역으로 정렬
## [[5,1,0], [4,3,2]]

# Flip : defualt로 axis =None
np.flip(arr)           # arr[::-1]와 같음, 모든축 반전
np.flip(arr, axis =0)  # 행기준 뒤집기
np.flip(arr, axis =1)  # 열기준 뒤집기


# Split() 기본이 axis = 0 (행)
arr = np.arange(2,61,2).reshape(10,3)
a,b,c,d,e = np.split(arr,5)           # 행기준 행번호없이 동일간격으로 5개 나누기
a,b,c = np.split(arr,[1,4]) 0행~, 1행~3행, 4행~ 잘라라 => 3개로 잘림
a,b,c = np.split(arr,[1,3], axis=1)

np.split(arr,3)   # 행기준 3등분
np.hsplit(arr,2)  # 열기준 2등분
np.vsplit(arr,3)  # 행기준 3등분

arr3d = np.array(24).reshape(2,3,4)
np.dsplit(arr3d,2)  #3차원배열 2x3x4 =(3번째축이 깊이축= 4]이것을 2로나눔> 2x3x2, 2x3x2

# 0이 아닌 요소 반환
np.nonzero(arr)

# 단위행렬
np.eye(3) # 3x3 단위행렬생성

# 변경불가능하게 옵션변경
arr.flags.writeable = False

# 일정간격으로 나누기 : 균등간격수열
np.linspace(0,1,5) #시작,끝,생성갯수(기본50개)
 ㄴ 0  <1>  0.25  <2>  0.5 <3> 0.75 <4>  1
 ㄴ 간격은 (1-0)/(5-1)로 계산 4개 간격을 가짐

# numpy type일치화 특성으로로 요소가 섞여있으면 큰 타입으로 승격됨(type promotion규칙)
숫자 + 문자 => 문자열로 승격, 숫자도 문자가됨
int, float -> float

arr.dtype     # 타입확인
arr.itemsize  # 각 항의 byte크기

np.array([1,2,4], dtype=np.int32)
np.array([3,4,5], dtype=np.str_)


# numpy broadcasting
(4x3) + (1x3) = (4x3)   # (1x3)이 동일하게 4개 행이 있다고 보고 산술연산함
(4x1) + (1x3) = (4x3)   # (4x1)이 동일하게 3개 열이 있다고 보고 산술연산함


# CSV파일 ==> Numpy loading
arr = np.loadtxt('c:/temp/stat.csv', delimiter=',', dtype=np.str_, encoding='utf-8')
##  기본적으로 숫자(float)로 읽으려고 시도, 문자가 섞여 잇으면 ValueError발생

# unpack=False 기본값 : 2차원 배열로 반환
# unpack=True 데이터를 읽을 때 행(row) 단위로 나눠서 각각 다른 배열에 담을 수 있음 
arr = np.loadtxt('c:/temp/stat.csv', skiprows=1, usecols=range(2,5), delimiter=',', dtype=np.int32)
#2,3,4열만 가져옴
arr_age = arr[:,0] #특정열 가져오기
arr_age.min()
arr_age.max()
arr_age.mean()

# array ===> file저장
np.savetxt('C:/temp/save.csv',arr, delimiter =',', fmt='%i' ) #fmt='%i' 포멧 정수
fmt = '%.2f'  # 소수점 둘째 자리까지 저장
fmt = '%f'    # 실수


# 결측치 처리 : 기본이 float
arr = np.genfromtxt('c:/temp', skip_header=1, delimiter=',')
## 기본이 float로 결측을 nan으로처리함
## dtype= np.int32로 하면 "-1"을 반환함 , 혼동소지가 있음 

arr = np.genfromtxt('c:/temp', skip_header=1, delimiter=',', filling_values=-99)



# -------------------------------------------
# Pandas
# -------------------------------------------

# Series : 1차원 배열
pd_seri = pd.Series([2,4,6])                 # 인덱스가 자동생성(0~)
pd_seri = pd.Series(5, index=[100,200,300])  # 5로 값이 모두생성됨
pd_seri = pd.Series(5, index=lise('abcde'))  # 5로 값이 모두생성됨
pd_seri = pd.Series({2:'a', 1:'b', 3:'c'}, index=[3,2]) #필터링기능
pd_seri = pd.Series(list)
pd_seri = pd.Series(arr)
pd_seri = pd.Series(np.array([1,2,4]))

pd_seri.loc[1]    # 명시적 인덱스
pd_seri.loc[1:3]  # 암묵적 인덱스
pd_seri.iloc[1]   # 암묵적 인덱스 , 숫자기반
pd_seri.iloc[1:3] # 암묵적 인덱스 , 숫자기반

pd_seri.values  # 데이터값
pd_seri.index   # 인덱스값

pd_seri[1]        # 명시적 인덱스사용
pd_seri[1:3]      # 인덱스가준 슬라이싱 i 암묵적 인덱싱
pd_seri['a']      # 인덱스 'a' value반환
pd_seri['a': 'f'] # 문자열 기준으로도 슬라이싱됨
pd_seri.head(3)   # 처음3개 요소만 반환
pd_seri.tail(3)   # 끝 3개 반환


area = pd.Series({'Alaska': 1723337, 'Texas': 695662, 'California': 423967}, name='area_name')
df = pd.Dataframe(area) # area_name 값은 데이터프레임에서 필드값명으로 사용
df = pd.Dataframe([area]) # 인덱스값으로 사용
df.area
df['area']
df.values
df.loc[df['density'] > 100, ['pop', 'density']]



# Dictionary -> Pandas.Series : 키값이 열
dict = {'a':0. , 'b':1}
pd_data = pd.Series(dict) # dict의 키값이 index가됨
pd_data = pd.Series(dict, index=[b,c,a]) # c는 없는값으로 NaN처리되서 보임

# 산술연산처리
pd_data1 = pd.Series([1,2,3])
pd_data2 = pd.Series([4,5,6])
pd_data1 + pd_data2 # numpy와 동일한 동장

df.subtract(df['r'], axis=0) # axis=0은 행연산 위에서 아래로..

# DataFrame 생성
pd.DataFrame(np.random.rand(3,2), columns=['foo', 'bar'], index=['a', 'b', 'c'], dtype=float)
##### 데이터, 열 필드명(columns), 행 필드명(index)
pd.DataFrame(SeriesData, columns=['population']) # series는 컬럼명이 없어 지정하고 index는 시리즈값을 활용

##### dataframe에서 dict의 키는 필드값임 //series에서는 인덱스로 사용됨 (주의!!)
dict ={'a' : [3,2,1], 'b': [1,2,3]}
df = pd.DataFrame(dict)

list = [{'x':1, 'y':2}, {'x':5,'y':2,'z':4}]
pd.DataFrame(list) # NaN값 나옴
pd.DataFrame(list, index=[1,2]) # NaN값 나옴

##### list comprehension활용
data = [{'a':i , 'b':2*i} for i in range(3)]
pd.Dataframe(data)

#### csv loading
df = pd.read_csv('c/temp', index_col=0) #0번 컬럼을 인덱스로 설정


# Ufuncs : 연산이 이뤄져도 원래의 인덱스와 컬럼 라벨을 그대로 유지
# NumPy ufuncs → 빠른 수학 연산 제공
ser = pd.Series([4, 7, 8, 2])
np.exp(ser) #각원오셍 exp적용되지만  시리즈 유지

df = pd.DataFrame([[1,2,3,4],[5,6,7,8],[9,10,11,12]], columns=list('ABCD'))
np.sin(df * np.pi / 4)



# Series 결측값처리
seri_a + seri_b                    # 인덱스에 없는 값은 NaN처리
seri_a.add(seri_b, fill_value=0)

seri_a.isnull()
seri_a.notnull()
seri_a[data.notnull()]        # 널값이 아닌것만 필터링할때 사용
seri_a.fillna(0)              # 결측치값 처리
seri_a.flllna(metho='ffill')  # 앞의 값으로 입력
seri_a.flllna(metho='bfill')  # 앞의 값으로 입력



# dataframe 결측값처리
fill = df_a.stack().mean()          #stack() 2차원구조를 1차원 시리스로 변환하고 평균값구함
df_a.add(df_b, fill_value= fill) 
df.dropna(axis='columns') #열기준으로 nan이 있으면 삭제

# dataframe 값 찾기
df.loc['인덱스']       # 해당 행 전체 가져옴
df.iloc['행','열']     # 암묵적인덱스
df.iloc[5, ::2]       # 2번씩 건너뛰면서 


# 계층적 인덱스 (Hierarchical indexing)
index = [(a,2000),(b,2010)]                     # 리스트의 경우 multiindex 처리가 필요
pop_index = pd.MultiIndex.from_tuples(index)
pop_index = pd.MultiIndex.from_arrays(index)
pop_index = pd.MultiIndex.from_product(index)   # 여러리스트의 곱
# from_product([리스트1, 리스트2]) → 두 리스트의 카르테시안 곱(Cartesian product)을 만들어서 인덱스로 사용
from_product([['a','b'], [1,2]])
첫 번째 리스트 ['a','b']
두 번째 리스트 [1,2]
가능한 모든 조합: (a,1), (a,2), (b,1), (b,2)

pop = pd.Series(list, index=pop_index)
pop[:,2010]                                     # 년도 인덱스의 값을 지정가능
pop.index.names = ['state','year']
pop[pop>200]

pop.sort_index() # 정렬


db = {(a,2000):1234,(b,2010):123]               # dictionary는 바로 인식
pd.Series(db)



# multiindex =>  unstack() : series를 차원이 있는값으로 만들어줌
df = pop.unstrack()    # 2계층이면 1계층은 인덱스/2계층은 열로 이동 
df.stack()             # 원복시킴

# pandas concat()
pd.concat([ser1,ser2])
pd.concat([ser1,ser2], axis=1)          # 열기준 합치기
pd.concat([ser1,ser2], keys=['x','y'])  # hierarchically indexed series
pd.concat([df1,df2], join =inner)
pd.concat([df1,df2], join =outer)

pd.merge(df1,df2)
pd.merge(df1, df2, on='employee')



# 컬럼을 기준으로 병합
pd.merge(df1, df2, left_on='employee', right_on='name')

# 인덱스를 기준으로 병합 : 기본값이 inner 교집합
result = pd.merge(df1, df2, left_index=True, right_index=True)
df1.join(df2)

pd.merge(df1,df2 how=inner or outer or left or right)

pd.merge(df1, df2, on='id', suffixes=('_left','_right')) # 이름이 같은필드 병합시 필드명 자동변경기준


# 행지우기
df.drop(['x','y'])
df.drop('b', axis =1)
df.drop(['x','y'], axis =1)

# 결측값제거
df.isnull.any()
df.dropna()

# groupby + aggregate() 추가해야함
df.groupby('key').aggregate([min,np.median,max])                # multiindex형태가됨
df.groupby('key').aggregate({'data1':[min,max], 'data2':max})   # 단일컬럼을 컬럼명 미표기

df.groupby('key').mean()              # 아래와 같은결과
df.groupby('key').aggregate(np.mean)    

# 필더를 거는데 df.groupby('key').std()의 의 결과값에서 data2필드를 보고 index를 판별하고 df.groupby('key')에 필털를 걸어 결과를 반환함
df.groupby('key').std()

def filter_func(x):
    return x['data2'].std() > 4

df.groupby('key').filter(filter_func)   

# groupby + transfromation() : 데이터를 줄이지 않고 원본의 크기와 모양을 유지하면서 값을 변경
def center(x):
    return x - x.mean()
df.groupby('key').transform(center)

# groupby + apply() : 그룹화된 결과에 임의의 함수를 적용
def norm_by_data2(x):
    x['data1'] /= x['data2'].sum()
    return x
df.groupby('key').apply(nor_by_data2)                      # multiindex형식으로 보임
df.groupby('key', group_keys=False).apply(norm_by_data2)   # multiindex형식으로 보임
df.groupby('key', group_keys=True).apply(norm_by_data2)    # key필드가 없어짐

# 새로운 리스트 그룹기반 그룹핑

L = [0,1,2,0,1,0]
df.groupby(L).sum()     #L 리스트를 기준으로 그룹핑해서 결과값 도출
df1.drop('key',axis=1)


# 열값중 인덱스 설정
df = pd.read_csv('c/temp', index_col=0) # 0번 컬럼을 인덱스로 설정
df.set_index('key')                     # df에서 별도로 설정하는방법

df2=df.set_index('key')                  # 원본은 변경되지 않으니 반환값을 별도 처리해줘야함
mapping ={'a':'vowel', 'b':'cosonat', 'c':'cosonat'}
# df.groupby(mapping).sum()               # value값으로 groupping
df2.groupby([str.lower, mapping]).mean()


df.groupby(['method',decade])['number'].sum().unstack() # multiindex 최하위 마지막값을 열로 올려줌
df.groupby(['method',decade])['number'].sum().unstack().flllna(0)

df.groupby('sex')[['survived]].mean()   # 이중대괄호를 사용해서 df구조유지, 필드값 유지
df.groupby('sex')['survived].mean()     # 시리즈 형태로 반환함, 컬럼명 없음

# pivot table
df.groupby(['method',decade])['number'].sum().unstack()    # multiindex 최하위 마지막값을 열로 올려줌
df.pivot_table('number', index='method', columns='decade') # pivot_table 활용

# pandas cut()
age = pd.cut(titanic['age'], [0,18,80])
df.pivot_table('survived', ['sex',age], 'class')

fare =pd.qcut(titla['fare'],2)
df.pivot_table('survived', ['sex',age], [fare,'class'])  # multiindex

# aggfunc 매개변수를 통해 각 컬럼별로 서로 다른 통계 함수를 적용
df.pivot_table(index = 'sex', columns='class', aggfunc={'survived':sum,'fare':mean})  # multiindex
births.pivot_table('births', index='decade', columns='gender', aggfunc='sum')
 

# pandas 문자열처리
s.capitalize() # list 첫글자만 대문자
s.upper()      # list
s.lower()      # list


seri.str.capitalize() # serises 첫글자만 대문자
seri.str.upper()      # serises
seri.str.lower()      # serises

df.description.str.contains('[Bb]reakfast').sum()  # description필드명 특정문자포함체크=> T/F값반환
df_sel = df.query('a & b & c') # a,b,c컬럼이 모두 true 인것을 반환
df_sel = df.query('a & b & ~c') # a,b,c컬럼이 모두 true 인것을 반환
df_sel = df.query('a and b and not c') # a,b,c컬럼이 모두 true 인것을 반환







# -------------------------------------------
# Matplotlib
# matplotlib              3.10.9
# matplotlib-inline       0.2.2
# -------------------------------------------

import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()

x = np.linspace(0,10,100)

# plt.plot() (Pyplot 인터페이스) : 코드가 짧고 간단
# matlab 스타일
plt.plot(x, np.sin(x), label = 'sin')
plt.plot(x, np.cos(x),'-.r' , label ='cos')

# 2. 산점도 그리기
plt.plot(..., marker='o')   # 산점도와 유사하나 개별적으로 특성지정어려움
plt.scatter()               # 점이 가진 개별적인 특성을 시각화 각 점마다 서로 다른 색상(c)과 크기(s)를 줄 수

# c=y : y축 값(높이)을 색상의 기준으로 삼음
# cmap='viridis' : 낮은 값은 보라색, 높은 값은 노란색으로 매핑
plt.scatter(x, y, c=y, s=sizes, alpha=0.5, cmap='viridis')



# fmt: 점의 모양과 선 스타일
# ecolor: 에러바의 색상
# elinewidth: 에러바 선 두께
# capsize: 에러바 끝부분 캡의 크기
# 오차의 크기 (모든 점에 동일하게 적용하거나 리스트로 개별 적용 가능)

plt.errorbar(x, y);
plt.errorbar(x, y, yerr=dy, fmt='.k', ecolor='red', capsize=3);
# yerr=dy 옵션을 통해 각 데이터 포인트마다 어느 정도의 오차(0.8)가 있는지 알려주었습니다.

# 축 설정
plt.xlim(-1,11)     # x축범위
plt.ylim(-1.5,1.5)
plt.axis([-1,11,-1.5,1.5])    # [xmin, xmax, ymin, ymax] 한번에사용
plt.axis('equal') #x축과 y축의 비율(Scale)을 동일하게 맞추는 역할

# 범례
plt.legend()

# 이미지 저장
fig.savefig('aaaa.png')              # 이미지 저장

# 그래프 화면에 표시
plt.show()                           # %matplotlib inline 코드가 없으면 show()가 있어야함





# ax.plot() (객체지향 인터페이스) 각 그래프 요소(축, 제목, 라벨 등)를 세밀하게 조절
fig = plt.figure()  # 전체 그래프 창 (가장 바깥 틀)
ax = plt.axes()     # 실제로 데이터가 그려지는 공간 (축과 그래프가 포함된 내부 영역)


ax = plt.axes()    
ax.plot([1, 2, 3], [4, 5, 6]) # 데이터 그리기
ax.set_title("My Graph")      # 제목 설정
ax.set_xlabel("X-axis")       # x축 라벨 설정



# Density and Contour Plots (등고선도)
import matplotlib.pyplot as plt
import numpy as np

# 1. 데이터 준비 (격자 만들기)
x = np.linspace(0, 5, 50)
y = np.linspace(0, 5, 40)

X, Y = np.meshgrid(x, y) # x, y 좌표를 조합해 전체 격자 포인트 생성
Z = np.sin(X) ** 10 + np.cos(10 + Y * X) * np.cos(X) # 높이 값(Z) 계산

# 2. 등고선 그리기
# colors='black' : 선의 색상을 검정으로 통일
plt.contour(X, Y, Z, colors='black');
plt.contourf(X, Y, Z, 20, cmap='RdGy'); 
# levels: 등고선을 몇 단계로 나눌지 결정합니다. 숫자가 클수록 선이 더 촘촘해
# 등고선 사이의 공간을 색상으로 가득 채워주는(Filled) 함수
plt.colorbar();

# 3. 선에 숫자 라벨 달기
plt.clabel(lines, inline=True, fontsize=8)



# 예시: 투명도를 조절한 히스토그램
# bins=30: 전체 데이터 범위를 몇 개의 구간(막대)으로 나눌지 결정합
plt.hist(data, bins=30, alpha=0.5, color='red', edgecolor='black');

# [left, bottom, width, height]
ax2 = plt.axes([0.65, 0.65, 0.2, 0.2])

plt.text(0.5, 0.5, str((2, 3, i)), ha='center') # 정중앙에 표시 예시 10, 1.05 (x, y 좌표): 텍스트가 시작될 위치

# 같은 열(Column)에 세로로 나열된 그래프들끼리 x축을 공유합니다.
sharex='col' (Column 공유)