Data_Analysis_Track_33/Python

Python_Pandas_02-3(DataFrame)

lsc99 2023. 9. 14. 19:29

5.2. 열 추가
- 새로운 열을 지정 후 값을 대입하면 새로운 열을 추가할 수 있다.
    보통 파생변수를 만들 때 사용한다.
- 열 추가

    df['col_name'] = value


    마지막 열로 추가된다.
    하나의 값을 대입하면 모든 행에 그 값이 대입된다.
    다른 값을 주려면 배열에 담아서 대입한다.
- 열 삽입
    df.insert(삽입할 위치 index, 삽입할 열이름, 값)
- 파생변수생성
    기존 열들의 값을 이용해서 만든 열을 파생변수라고 한다.
    벡터화 연산을 이용하여 값 대입한다.
    df['col_name'] = 기존 열들을 이용한 연산

 

변수 grade에 grade2.csv 파일 읽어오기

import pandas as pd

grade = pd.read_csv("saved_data/grade2.csv")
grade.set_index("id", inplace=True)
grade

컬럼을 추가

# 컬럼을 추가
grade["수학"] = 100 # 수학 컬럼을 생성, 모든행에 100을 대입. 없는 컬럼에 값 대입 -> 추가
grade

있는 컬럼에 값을 대입 -> 수정

grade["수학"] = 80 # 수학컬럼의 값을 변경. 있는 컬럼에 값을 대입 -> 수정
grade

리스트 형태로 값 삽입

grade["수학"] = [70, 100, 90, 40, 70] # 값의 개수 = 행수. 1차원 자료구조(리스트, 시리즈), 시리즈로 사용시 index name이 일치해야함
grade

Series 사용하여 값 삽입

grade['과학'] = pd.Series([70, 100, 90, 40, 70], index = grade.index) # Series 사용
grade

series + series -> 같은 행의 값끼리 계산한다.

# series + series -> 같은 행의 값끼리 계산한다.
sum_result = grade['국어'] + grade['영어'] + grade['수학'] + grade['과학']
sum_result

파생변수 생성

# 파생변수 생성
grade['총점'] = sum_result
grade

파생변수 생성

# 파생변수 생성
grade['평균'] = grade['총점'] / 4
grade

grade.to_csv('saved_data/grade_result.csv') # csv파일로 작업 저장

# 변수 r에 저장된 csv파일 읽어오기
r = pd.read_csv('saved_data/grade_result.csv', index_col=0)
r

변수 grade에 다시 grade2.csv 파일 읽어오기

grade = pd.read_csv('saved_data/grade2.csv', index_col='id')
grade

axis

# axis = 1 -> 행끼리의 합, axis = 0 -> 열끼리의 합
total = grade.sum(axis=1)
mean = grade.mean(axis=1)
grade['총점'] = total
grade['평균'] = mean
grade

 

TODO

- 패스 여부를 boolean값으로 저장하는 파생변수 열을 추가
    열이름: 합격여부
    평균점수가 80미만이면 False,이상이면 True가 나오도록 처리

 

grade['합격여부'] = grade['평균'] >= 80
grade

numpy를 이용한 파생변수 열 추가

import numpy as np
grade['합격여부2'] = np.where(grade['평균'] >= 80, '합격', '불합격') # True : 합격, False : 불합격 으로 변경
grade

행, 열의 값 조회
- indexer 연산자를 이용한다.
    행은 loc indexer, iloc indexer를 사용한다.
- 열은 indexing만 되고 slicing은 안된다.
- 행은 indexing, slicing 모두 지원한다.

6.1. 열의 값 조회
- df['열이름']
    열이름의 열 조회
- df.열이름
    열이름이 Python 식별자 규칙에 맞으면 . 표기법을 사용할 수 있다.
- Fancy indexing

    여러개의 열들을 한번에 조회할 경우 열이름들을 리스트로 묶어서 전달한다.
- 주의
    열은 순번으로는 조회할 수 없다.
    열 조회 indexer에서 슬라이싱을 하면 행 조회 Slicing이다.
    만약 indexing이나 slicing을 이용해 열들을 조회하려면 columns 속성을 이용한다. -> df[df.columns[:3]]

 

grade['국어'] # 한개 열 조회 -> Series 로 반환.

grade.국어

두 개 이상의 열 조회

grade[['평균', '총점']] # 여러 열을 조회 -> DataFrame으로 반환

 

grade['국어':'평균'] # 행 조회로 바뀐다.
grade[0:3]

column 속성 이용하여 indexing, slicing

grade[grade.columns[0:4]] # columns 속성을 이용하여 indexing과 slicing을 한다.

TODO

- 다음 movie dataframe을 이용해 코드를 작성

 

변수 df에 movie_df.csv 파일 읽어오기

import pandas as pd

df = pd.read_csv('saved_data/movie_df.csv')
df.head()

 

# 1.  director_name 컬럼의 값들 조회
df['director_name']

 

# 2. actor_1_name, actor_2_name, actor_3_name 컬럼의 값들 
df[['actor_1_name', 'actor_2_name', 'actor_3_name']]

 

# 3. 1, 3, 4, 7 번 컬럼 조회('director_name', 'duration', 'director_facebook_likes', 'actor_1_facebook_likes')
# df[['director_name', 'duration', 'director_facebook_likes', 'actor_1_facebook_likes']]
df.drop(columns = 'Unnamed: 0', inplace=True) # 0번 컬럼의 Unnamed: 0 삭제
df[df.columns[[1, 3, 4, 7]]]

 

# 4. 1 ~ 5 번 컬럼 조회('director_name', 'num_critic_for_reviews', 'duration', director_facebook_likes', 'actor_3_facebook_likes')
df[df.columns[1:6]]

6.1.1. 다양한 열선택 기능을 제공하는 메소드들
- select_dtypes(include=[데이터타입,..], exclude=[데이터타입,..])
    전달한 데이터 타입의 열들을 조회.
    include : 조회할 열 데이터 타입
    exclude : 제외하고 조회할 열 데이터 타입
- filter (items=[], like='', regex='')
    매개변수에 전달하는 열의 이름에 따라 조회
    각 매개변수중 하나만 사용할 수 있다.
    items = [컬럼명들, ..]
        - 리스트와 일치하는 열들 조회
        - 이름이 일치 하지 않아도 Error 발생안함.
    like = '부분일치문자열'
        - 전달한 문자열이 들어간 열들 조회
        - 부분일치 개념
    regex = '정규표현식'
       - 정규 표현식을 이용해 열명의 패턴으로 조회

 

 

grade.info()

include, exclude

# 데이터 타입으로 조회
# include : 조회하고 싶은 타입들을 지정.
# grade.select_dtypes(include='int64')
grade.select_dtypes(include=['int64', 'bool']) # 특정 데이터 타입의 열을 조회

##  exclude: 조회 안할 타입들을 지정.
grade.select_dtypes(exclude=["object", "bool"])

grade_result 생성

grade_result = pd.read_csv("saved_data/grade_result.csv", 
                           index_col=0)
grade_result

컬럼을 중간에 삽입

# 컬럼을 중간에 삽입
grade_result.insert(loc=1, column='국어2', value = 90)

grade_result.insert(loc=4,              # 컬럼을 삽입할 위치 -> 순번으로 지정
                    column='수학2',      # 컬럼이름
                    value=[100,80,55,85,57])
                    
grade_result

filter

grade_result.filter(items=['국어', '국어2', '국어3']) # filter 국어3은 없는 컬럼이여서 조회되지 않는다.

grade_result.filter(like='국어') # 컬럼명에 '국어' 가 들어가는 컬럼들을 조회

정규표현식 이용

#  ^ : 시작    .{2} : 두글자     $ : 끝
grade_result.filter(regex=r"^.{2}$") # 정규표현식과 일치하는 컬럼들을 조회
grade_result.filter(regex=r".+어$") # 어 로 끝나는 컬럼 조회

컬럼의 순서를 원하는 순서로 변경

# 컬럼의 순서를 변경 -> 원하는 순서로 조회(fancy indexing 활용)
g = grade_result[['국어','국어2', '수학', '수학2', '영어', '과학', '평균', '총점']]
g

TODO

movie dataframe을 이용해 아래 코드를 작성하시오.

 

# 1. 정수형(int64) 컬럼만 조회
df.select_dtypes(include = 'int64')

 

# 2. 정수형(int64)과 실수형(float64) 타입을 제외한 컬럼들만 조회
df.select_dtypes(exclude=['int64', 'float64'])

 

# 3. actor_1_name, actor_2_name, actor_3_name 컬럼의 값을 조회
# df.filter(['actor_1_name', 'actor_2_name', 'actor_3_name'])
df.filter(regex=r"actor_\d_name") # 정규 표현식 이용

 

# 4. actor_1_facebook_likes, actor_1_name 컬럼의 값을 조회
# df.filter(['actor_1_facebook_likes', 'actor_1_name'])
df.filter(like = 'actor_1_')

 

# 5. color, director 컬럼을 조회. 없는 컬럼명이라도 에러가 안나도록 조회하시오.
df.filter(items = ['color', 'director'])

 

# 6. movie가 들어가는 컬럼들을 조회.
df.filter(like = 'movie')

6.2. 행 조회
- loc : index 이름으로 조회
- iloc : 행 순번으로 조회

6.2.1. loc indexer
- index name으로 조회
- DF.loc[ index이름 ]
    한 행 조회.
    조회할 행 index 이름(레이블) 전달
    이름이 문자열이면 " " 문자열표기법으로 전달. 정수이며 정수표기법으로 전달한다.
- DF.loc[ index이름 리스트 ]
    여러 행 조회.
    팬시 인덱스
    조회할 행 index 이름(레이블) 리스트 전달
- DF.loc[start index이름 : end index이름: step]
    슬라이싱 지원
    end index 이름의 행까지 포함한다.
- DF.loc[index이름 , 컬럼이름]
    행과 열 조회
    둘다 이름으로 지정해야 함.

 

grade.loc['id-3'] # series로 반환 index 이름 : 컬럼명

grade.loc[['id-2', 'id-4']]

grade.loc['id-2' : 'id-4'] # slicing, end index 포함시킨다.

grade['id-5':'id-2':-1] # reverse

행, 열 같이 조회

# 행, 열을 같이 조회
# loc[행이름, 열이름] : 행/열 - indexname, fancy indexing, slicing
grade.loc['id-2', '총점']
grade.loc[['id-2', 'id-3'], '총점']
grade.loc[['id-2', 'id-5'], ['총점', '평균']]
grade.loc['id-1':'id-4', ['국어', '평균']]
grade.loc['id-2':'id-4', '영어':'합격여부']

 

# loc index : 행/열 모두 이름으로 조회. (순번은 사용못함.)
# grade.loc[1:3]
# grade.loc['id-3', 1]

# indexer 안에서 행, 열을 같이 조회하는 것은 loc,iloc indexer만 가능
grade['국어']['id-2']
grade[['국어','영어']].loc['id-2']

 

6.2.2. iloc
- index(행 순번)으로 조회
- DF.iloc[행번호]
    한 행 조회.
    조회할 행 번호 전달
- DF.iloc[ 행번호 리스트 ]
    여러 행 조회.
    조회할 행 번호 리스트 전달
- DF.iloc[start 행번호: stop 행번호: step]
    슬라이싱 지원
    stop 행번호 포함 안함.
- DF.iloc[행번호 , 열번호]
    행과 열 조회
    행열 모두 순번으로 지정

 

grade.iloc[0]
grade.iloc[2]
grade.iloc[[0, 2, 3]]
grade.iloc[1:3]
grade.iloc[1:-1] # 음수 index 가능
grade.iloc[1, 2] # iloc -> 행/열 모두 순번(index)으로 조회
grade.iloc[[2, 4], 2]
grade.iloc[:4, [0, 1]]
grade.iloc[1:3, 1:]

TODO

- movie dataframe을 이용해 loc과 iloc관련해 다음을 작성

 

# 1.  movie_title 컬럼을 index명으로 지정
import pandas as pd

df = pd.read_csv('saved_data/movie_df.csv')
df1 = df.set_index('movie_title')
df1

 

# 2.  행이름이 Avatar인 행 조회
df1.loc['Avatar']

 

# 3.  행이름이 Spider-Man 3, The Avengers, Titanic 인 행 조회
df1.loc[['Spider-Man 3', 'The Avengers', 'Titanic']]

 

# 4.  행이름 Spectre ~ Robin Hood 까지 범위로 조회
df1.loc['Spectre':'Robin Hood']

 

# 5.  행이름이 John Carter 이고 열이름이 director_name 인 값 조회 - John Carter의 감독이름
df1.loc[['John Carter'], ['director_name']]

 

# 6.  1번행 조회
df1.iloc[1]

# 7.  마지막 행 조회
df1.iloc[-1]

# 8.  1, 2, 5, 6, 9 번행 조회
df1.iloc[[1, 2, 5, 6, 9]]

# 9.  10 ~ 20 행 조회
df1.iloc[10:21]

 

# 10.  movie dataframe에서 5 ~ 10 행의 color, director_name, num_critic_for_reviews 컬럼(0,1,2번째 컬럼)을 iloc을 이용해 조회
df1.drop(columns = ['Unnamed: 0'], inplace=True)
df1.iloc[5:11, 0:3]

6.3. Boolean indexing을 이용한 조회
- 원하는 조건을 만족하는 행, 열을 조회한다.

- DataFrame객체[조건], DataFrame객체.loc[조건]

    조건이 True인 행만 조회
    열까지 선택시
        DataFrame객체[조건][열]
        DataFrame객체.loc[조건, 열]

- iloc indexer는 boolean indexing을 지원하지 않는다.

- 논리연산자
논리연산자 설명


        &         and연산
        |          or연산
       ~          not 연산


    논리연산자의 피연산자들은 반드시 ( )로 묶어준다.
    파이썬과는 다르게 and, or, not 예약어는 사용할 수 없다.

 

df[df['color'] == 'Color'] # 조건이 True인 행이 조회 -> sql select의 where절

df.loc[df['color']=='Black and White']

df.loc[df['color'] == 'Black and White', ['movie_title', 'director_name']]

 

국어 80점 이상

grade[grade['국어'] >= 80]
grade.loc[grade['국어'] >= 80] # iloc은 boolean indexing을 지원하지 않는다.

국어 70점 이상인 행의 국어 평균 총점 출력

grade.loc[grade['국어'] >= 70, ['국어','평균','총점']]
grade[grade['국어']>=70][['국어','평균','총점']] # 같은 의미이다.

and, or

# 국어, 영어 모두 80점 이상(and)
grade.loc[(grade['국어'] >= 80) & (grade['영어'] >= 80)]

# 국어, 영어 둘 중에 하나 80점 이상(or)
grade.loc[(grade.국어 >= 80) | (grade.영어 >= 80)]
grade.loc[~((grade.국어 >= 80) | (grade.영어 >= 80))]

TODO

- movie dataframe

 

# 1.  상영시간 (duration)이 300 이상인 영화들 조회
df.loc[df['duration'] >= 300]

 

# 2.  상영시간 (duration)이 300 이상인 영화들의 영화제목(movie_title)과 감독이름(director_name) 조회
df.loc[df['duration'] >= 300, ['movie_title', 'director_name']]

 

# 3.  감독이름(director_name)이 'Quentin Tarantino' 의 영화들만 조회
df.loc[df['director_name'] == 'Quentin Tarantino']

 

# 4. James Cameron의 영화중 상영시간이 150분 이상인 영화들의 제목(movie_title), 상영시간(duration), 컬러여부(color) 조회
df.loc[(df['director_name'] == 'James Cameron') & (df['duration'] >= 150), ['movie_title', 'duration', 'color']]

query() 를 이용한 boolean indexing
- query(조회조건)
    sql의 where 절의 조건 처럼 문자열의 query statement를 이용해 조건으로 조회
    boolean index에 비해
        - 장점: 편의성(문자열로 query statement를 만들므로 동적 구문 생성등 다양한 처리가 가능)과 가독성이 좋다.
        - 단점: 속도가 느리다.
- 조회조건 구문
    "컬럼명 연산자 비교값"
- 외부변수를 이용해 query문의 비교값을 지정할 수 있다.
    query 문자열 안에서 @변수명 사용
    f string이나 format() 함수를 이용해 query를 만들 수도 있다.


6.4.1. query 함수 연산자
- 비교 연산자
    ==, >, >=, <, <=, !=
- 결측치 비교
    컬럼.isna(), isnull()
    컬럼.notna(), notnull()
- 논리 연산자
    and, or, not
- in 연산자
    in, ==
    not in, !=
    비교 대상값은 리스트에 넣는다.
- Index name으로 검색
    행의 index 이름으로 검색
- 문자열 부분검색(sql의 like)
    컬럼명.str.contains(문자열): 문자열을 포함하고 있는
    컬럼명.str.startswith(문자열): 문자열로 시작하는
    컬럼명.str.endswith(문자열): 문자열로 끝나는
    문자열 부분검색을 할 컬럼에 결측치(NaN)이 있으면 안된다.

 

DataFrame 생성

import pandas as pd
import numpy as np
data_dict = {
    'name':['김영수', '박영희', '오준호', '조민경', '박영희', '김영수'],
    'age':[23, 17, 28, 31, 23, 17],
    'email':['kys@gmail.com', 'pyh@gmail.com', 'ojh@daum.net', 'cmk@naver.com', 'pyh@daum.net', np.nan]
}
df = pd.DataFrame(data_dict)
df

실습

# 비교연산
df.query("name == '김영수'")
df.query("age > 25")
df.query("name != '김영수'")

# 결측치 비교
df.query("email.isnull()")  # 결측치인 것 조회 (or isna())
df.query("email.notnull()") # 결측치가 아닌 것 조회(or notna())

# 논리연산
df.query("not age < 25") # not -> 논리부정
df.query("~(age < 25)")  # ~ -> 논리연산자(부정)

df.query("name == '박영희' and age > 20")
df.query("name == '박영희' & age > 20") # ()로 안묶어도 됨.

df.query('name == "박영희" or age > 25')
df.query('name == "박영희" | age > 25')

# in, not in 연산자, ==, !=
df.query('age in [17, 23]')
df.query('age == [17, 23]')

df.query('age not in [17, 23]')
df.query('age != [17, 23]')

# index 이름의 조건으로 비교 -> 컬럼명자리에 "index"
df.query("index > 3")

df.set_index("name").query("index == '김영수'")
df.set_index("name").query("index > '박영희'")

# 문자열 부분조회 (sql의 like 기능)
# ~로 시작하는지?
df.query("name.str.startswith('김')") # 김 으로 시작한다

# ~로 끝나는지?
df.query("name.str.endswith('희')")

# ~를 포함하는지?
df.query("name.str.contains('민경')")

# 부분일치 함수 사용하는 컬럼에는 결측치가 있으면 안된다.
# df.query("email.str.endswith('.com')") -> 오류발생

# 결측치가 있을 경우 -> 결측치 아닌 것들을 조회하고 부분일치 조회.
df.query('email.notnull()').query("email.str.endswith('.com')")

# 조건 비교해서 사용할 값으로 외부의 변수값을 이용하기
first_name = '김'
# df.query(f')
df.query('name.str.startswith(@first_name)')

name = input("이름:")
age = int(input("나이:"))
# 변수의 값의 타입에 맞춰서 query문을 처리
df.query("name == @name and age == @age")

TODO

movie dataframe을 이용해 query() 메소드를 사용

 

# 1. 상영시간이 300분 이상인 영화들만 조회
df.query("duration >= 300")

 

# 2. 상영시간이 250분 ~ 300분 인 영화들 조회
df.query("duration >= 250 and duration <= 300")

 

# 3. 컬러영화가 아닌 영화 조회
df.query("not color == 'Color'")

 

# 4. 이름에 James가 들어가는 감독의 영화조회

df.query("director_name.notnull()").query("director_name.str.contains('James')")