ㅅㅇ

Pandas _ 02-4 DataFrame 접근 _ 컬럼/행의 값 조회 및 변경 본문

AI_STUDY/Pandas

Pandas _ 02-4 DataFrame 접근 _ 컬럼/행의 값 조회 및 변경

SO__OS 2022. 6. 8. 22:22
플레이데이터 빅데이터캠프 공부 내용 _ 6/8

Pandas_02-4 DataFrame 접근 _ 컬럼/행의 값 조회 및 변경

1. 열 (컬럼) 조회 _ 방법 1 ) 대괄호 

(1) df [ '컬럼명' ]     # 열 순번 안됨. 슬라이싱도 안됨. - > 하면 인덱스 순번으로 인식한다.

      : 한 컬럼(열) 조회.

        =>  series 로 반환.  결과의  index명 = DF 행 index명 

     

# 1. 한 컬럼(열)을 조회할 경우 series 로 반환.
grade['국어']

    - > Series로 반환

# series의 index명(각각의 값의 키로)으로 DF의 index명이 온다.
# Name : 국어 => 국어 컬럼 조회한 결과야.
ID
id-1    100.0
id-2     50.0
id-3      NaN
id-4     90.0
id-5     85.0
Name: 국어, dtype: float64

 

(2) df.컬럼명
    - 컬럼명이 변수 규칙에 맞을 경우만 사용 가능.

# 2. 
grade.합계

# grade.점수 합계  # 변수 규칙에 맞지 않는 컬럼이름은 점 표기법으로 조회할 수 없다. 에러.!
grade['점수 합계']

 

(3) 팬시 indexing  

     : 한번에 여러 개의 컬럼을 조회할 경우 컬럼명들을 담은 리스트로 조회

       =>  Fancy indexing : 조회할 컬럼들을 '리스트로 묶어서' 전달
       =>  DataFrame 로 반환.

# 3. 한번에 여러 컬럼의 값을 조회할 경우 => Fancy indexing 
grade[['점수 합계', '평균', 'pass']]

- 주의

    - 대괄호 조회는 없는 컬럼의 경우 exception을 발생시킨다.
    - df[컬럼 열 순번 ] 는 안된다.  

    - df[0:3] 슬라이싱도 안한다. 슬라이싱은 행 조회다.

    = > 만약 indexing이나 slicing을 이용해 컬럼값 조회하려면 df.columns 속성  을 이용한다.
        - `df [ df.columns[ 1 : 3 ] ]`

# 컬럼의 순번으로 조회해야 하는 경우가 있다면?
grade[grade.columns[:4]]

# 이렇게 순번으로 조회하고 싶을 때를 위해 컬럼명을 변수에 미리 담아둔다.
cols = grade.columns
grade[cols[:4]]

 

2. 열 (컬럼) 조회 _  방법 2)  다양한 열선택 기능을 제공하는 메소드들 

2.1 특정 데이터 타입 의 열들을 조회

select_dtypes(include=[데이터타입,..], exclude=[데이터타입,..])

    - 전달한 데이터 타입의 열들을 조회. 
    - include : 조회할 열 데이터 타입
    - exclude : 제외하고 조회할 열 데이터 타입

# float64, int64 타입의 컬럼만 조회
grade.select_dtypes(include = ['float64','int64'])

# float64, int64 타입의 컬럼을 제외하고 조회
grade.select_dtypes(exclude = ['float64', 'int64'])

 

2.2 매개변수에 전달하는 열의 이름에 따라 조회

filter (items=[], like='', regex='')

    - 각 매개변수 중 하나만 사용할 수 있다.

(1) items = [    ]   

     - 리스트와 일치하는 열들 조회

     - 하나의 열 조회에도 DF로 반환한다. 

     - 이름이 일치하지 않아도 Error 발생 안함.   // 대괄호 방법은 없는 열 조회 시 exception 발생

            - 다중 열 조회 시 없는 컬럼이 있더라도, 없는 컬럼 제외하고 조회

# 하나의 열 조회 DF 반환
grade.filter(items=['국어'])

# 다중 열 조회 DF 반환
grade.filter(items=['국어','수학','지리'])

 

(2) like = '   '

     - 전달한 문자열이 들어간, 부분일치하는 열들 조회. 부분일치 개념

     - 하나만 가능.

     - 많이 쓴다.

 

# 국어과목을 다 조회하고 싶다면?
# 컬럼명에 '국어'가 들어가는 컬럼들을 모두 조회

grade.filter(like = '국어')

 

 

(3) regex = '   '

     - 정규 표현식을 이용해 열 명의 패턴으로 조회

 

# \w 어떤 값들이 들어온다라는 뜻  
# 2$ : 2 로 끝이난다라는 뜻

\d  : 숫자 한글자

# \d$  : 정수로 끝이 난다라는 뜻

# [123] : 1또는2또는3이 이곳에 자리한다라는 뜻

# 사이에는 + 로 이어준다.

grade.filter(regex=r"\w+2$")  #2로 끝나는 컬럼을 조회 
grade.filter(regex=r"\w+\d$") # 정수로 끝나는   

# actor_1_name, actor_2_name, actor_3_name 컬럼의 값을 조회
movie_df.filter(regex=r'actor_\d_name') 
movie_df.filter(regex=r'actor_[123]_name')

 

 

지금까지 마치 SQL의 select절처럼 전체 조회 또는 특정 컬럼에 대해 조회를 했다.

그렇다면, 이제 원하는 행을 조회할 것이다.

 

Series는 1차원 구조로 index명과 값으로만 이뤄져 있다. 그렇기에 대괄호 조회든 록 아이록 조회든 결과는 동일하다.

하지만, 데이터 프레임의 경우,

컬럼 조회와 행 조회에 따라 사용해야 할 방법이 다르다.

 

3. 행 조회 _ loc, iloc

     loc : index 이름으로 조회

     iloc : 행 순번으로 조회 (음수 인덱스 양수 인덱스)

    - 함수가 아니다. indexer 변수이다. 뒤에 대괄호가 붙는다.

 

3.1  loc : 행 이름 (index 명)으로 조회

 

(1) DF.loc[ index이름 ]
    - 한 행 조회.
    - 조회할 행 index 이름(레이블) 전달
    - 이름이 문자열이면 " " 문자열표기법으로 전달. 정수이며 정수표기법으로 전달한다.

 

# id-3 행을 조회 - 한행 조회 => Series로 반환 (index명 : 컬럼명)
grade.loc['id-3']

 

 

(2) DF.loc[ index이름 리스트 ]
    - 여러 행 조회. 
    - 팬시 인덱스 
    - 조회할 행 index 이름(레이블) 리스트로 묶어 전달

 

# id-3 , id-5  여러행 조회 => DataFrame로 반환
grade.loc[['id-3','id-5']]

 


(3) DF.loc[start index이름  :  end index이름: step]
    - 슬라이싱 지원
    - end index 이름의 행까지 포함한다.! (이름으로 슬라이싱할 때는 포함!!)

grade.loc['id-2':'id-4']
grade.loc[::2]
grade.loc['id-5':'id-2':-1]

 

 

(4) 특정 value를 조회 - 행과 열을 지정해서 조회

     DF.loc[index이름 , 컬럼이름]      .loc[행, 열]  

 

** grade.loc[국어, 수학]이 안되는 이유. 펜싱인덱싱 늘 리스트로 묶어야 하는 이유

 

grade.loc['id-2','영어'] # 행 'id-2'  열 '영어'  인 값

 

- [행, 열] 틀에서 행과 열을 인덱싱, 슬라이싱, 펜싱해서 작성가능. 조합해서도 가능.

# 행, 열을 loc으로 같이 조회할 경우 행과 열에 슬라이싱 할 수 있다.
grade.loc['id-2':'id-4', '수학':'과학']

# 행에 슬라이싱, 열에 펜싱
grade.loc['id-2':'id-4', ['수학','과학']]

 

- 컬럼 명 조회 결과가 시리즈라 이렇게도 조회가능하지만, 굳이 안 쓰고 위 방법 사용.

# grade.loc['id-2']['영어']

 

 

3.2  iloc : 행 순번 (인덱스 순번) 으로 조회

- 양수인덱스, 음수인덱스 


(1) DF.iloc[행번호]
    - 한 행 조회.
    - 조회할 행 번호 전달


(2) DF.iloc[ 행번호 리스트 ]
    - 여러 행 조회.
    - 조회할 행 번호 리스트 전달


(3) DF.iloc[start 행번호: stop 행번호: step]
    - 슬라이싱 지원
    - stop 행번호 포함 안함.

 

# 0번 행을 조회
grade.iloc[0]

# 음수 index => -1 : 마지막 행
grade.iloc[-1]

# 여러 행 조회 - 펜싱
grade.iloc[[1,3,-1]]

# slicing - iloc indexer의 경우 end index는 포함하지 않는다.
grade.iloc[1:4]

# 역순 reverse 전체 조회
grade.iloc[::-1]

 

(4) DF.loc[행번호 , 열번호]
    - 행과 열 조회
    - 행열 모두 순번으로 지정

 

 # 1번째행의 3번 컬럼
 grade.iloc[1,3]
 
 # 펜시, 슬라이싱으로 담아서도 가능.
 grade.iloc[[0,3],[1,3,5]]
 grade.iloc[[0,3],:4]
 grade.iloc[1:4,5:9]

 

4. Boolean indexing을 이용한 조회

행, 열에 조건식을 이용해 원하는 조건의 행이나 열을 조회
- 보통, 행 조회 시 사용한다. (sql where 절 처럼)

 

- 조건 : bool series  => 조건을 행(인덱스) 또는 열(컬럼) 조회 자리에 넣어서!

   ex) grade['국어'] >= 70

 

- 다중 조건의 경우 ( )로 묶는다.
- 논리연산자  &    |     ~

- iloc[]은 boolean indexing을 지원하지 않는다.

 

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

   -  조건이 True인 행만 조회

   - 열까지 선택시
          -   DataFrame객체[조건][열]
          -   DataFrame객체.loc[조건, 열]

 

ex1) 국어점수가 70점 이상인 행

 

조건 : grade['국어'] >= 70      == > bool series 
 bool series에서  True 인 행을 조회한다.

 # True 인 행을 조회
grade[grade['국어']>=70]

 

ex2) 국어점수가 70점 이상인 행의 '국어', '평균'
        grade[grade['국어'>=70]]      == > 데이터 프레임 

                                                     == > 데이터 프레임의 컬럼을 선택해 조회

 

grade[grade['수학']>=75][['수학','평균']]

 

ex3) 수학이 100점인 행

 

grade.loc[grade['수학']==100]

 

ex4) 수학이 100점인 행의 수학과 평균을 조회

 

#1 조회결과가 데이터 프레임  => 데이터 프레임의 컬럼을 선택해 조회
grade.loc[grade['수학']==100][['수학','평균']]

#2 loc[행, 열] : loc[boolean indexing, 열선택]
grade.loc[grade['수학']==100, ['수학', '평균']]

 

- 다중 조건 논리 연산자 사용

# 수학 100점이고 과학은 60점 이상 (둘다 True 행을 조회 => &)
grade.loc[(grade['수학']==100) & (grade['과학']>=60), ['수학','과학']]


# 수학이 100점이거나 paas2 불합격(pass=False)
grade[(grade['수학']==100) | (grade['pass2']=='불합격')][['수학','pass2']]

# 수학이 100점이 아닌 행
grade.loc[~(grade['수학'] == 100),'수학']

 

5. query() 를 이용한 boolean indexing

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

    - query 문자열 안에서 @변수명 사용   (변수에 담아둔 값을 불러와 조건의 피연산자가 된다.)
    - f string이나 format() 함수를 이용해 query를 만든다.

 

# 외부 변수에 값을 query 구문에서 사용
name = "신비한"
df.query("name == @name") # 변수에 담긴 데이터 문자열로 인식해 조건 찾는다.

# f.string 방법
name = '박영희' 
df.query(f"name == '{name}'")


    
[ 연산자 ]
(1) 비교 연산자
    - ==, >, >=, <, <=, !=

 

df.query("age == 32")
df.query("tall>=170")

# 문자열이 들어갈 때 쌍 홀 따옴표 쓰기
df.query("name == '김영수'")

    
(2) 결측치 비교 - Series 의 메소드 사용
    - 컬럼.isna(), isnull()
    - 컬럼.notna(), notnull()    

 

# 결측치 조회- Series의 메소드 사용
df.query("tall.isnull()", engine='python')
df.query("tall.isna()", engine='python')

df.query("tall.notnull()", engine='python')
df.query("tall.notna()", engine='python')

 

(3) 논리 연산자
    - and(&), or(|), not(~)
    - 피연산자 괄호는 ~() 일때만. not 붙이면 괄호 안 씀.
 

# 논리연산 and &
df.query("age >20 & tall > 180")
df.query("age >20 and tall > 180")

# 논리연산 or |
df.query("age> 30 | tall > 190")
df.query("age> 30 or tall > 190")

# 논리연산 not ~()
df.query("~(tall<190)")
df.query("not tall<190")

 
(4) in 연산자
    - in, ==
    - not in, !=
    - 비교 대상값은 '리스트'에 넣는다.

df.query("name in ["강강찬", "이순신"]")
df.query("name not in ['강감찬', '이순신']")

# 이렇게도 가능하긴 하다.
df.query("name == ['김영수','강감찬']")
df.query("name != ['김영수','강감찬']")

    
(5) Index name으로 검색
    -  원하는 행을 직접 행 이름으로 검색하는 것. 

    - 순번이 아니다. 인덱스 명으로 하는 것이다. (현재 예제 데이터프레임의 인덱스명이 순번으로 지정되어 있을 뿐) 

df.query("index > 3 ")
df.query("index == [1, 5, 6]")

         


(6) 문자열 부분검색     (sql의 like)
    - 컬럼명.str.contains(문자열) : 문자열을 포함하고 있는 
    - 컬럼명.str.startswith(문자열) : 문자열로 시작하는
    - 컬럼명.str.endswith(문자열)  : 문자열로 끝나는

# 1. 특정 문자열을 포함하는
df.query('name.str.contains("영")', engine = 'python')
# 2. 특정 문자열로 시작하는
df.query('name.str.startswith("김")', engine = 'python')
# 3. 특정 문자열로 끝나는
df.query('name.str.endswith("동")', engine = 'python')

 

    - 문자열 부분검색을 할 컬럼에 결측치(NaN)이 있으면 안된다.

        - > 방법1 논리연산자 and 로 null인 것 제외

             파이썬의 경우 and 연산일 때 앞의 피연산자 조건이 틀리면 뒤 조건을 보지도 않음.

movie_df.query('director_name.notnull() and director_name.str.contains("James")', engine='python')

        - > 방법2 

               현재, 조건이 담긴 문자열에서 NaN 값이 존재할 경우 True 또는 False가 아니라 NaN을 반환한다.

               이 결과를 받아 행을 취득하려고 하면 당연히 에러 발생.

               이때, na를 True나 False로 치환해준다.

               결측치 포함하려면 : na = True,   결측치 포함하지 않으려면 na = False 

# 결과 데이터프레임에 결측치 미포함
movie_df.query('director_name.str.contains("James", na = False)', engine='python')

# 결과 데이터프레임에 결측치 포함
movie_df.query('director_name.str.contains("James", na = True)', engine='python')

 

 

- Series 메소드 사용하는 (2) (6) 의 경우, error 발생할 수 도 있다.

TypeError: unhashable type: 'Series'

파이썬 넘파이 버전 문제인 것 같기도 하지만, 일단 다시 설치를 하기가 힘들어 방법을 구글링하였다.

구글링 결과 query 함수에 들어가는 쿼리문을 해석하는 엔진 기본값으로 'numexpr' 로 설정되어 있고

이 엔진이 isnull 함수를 해석하지 못하기 때문이라고 한다.

 => 엔진을 바꿔주면 된다. 아래와 같이 engine 인자에 'python' 을 넣어주면 된다.

df.query('B.isnull()', engine='python')

 

 

** (참고) 쥬피터 노트북에서는 print 안 하고 바로 반환해야 한다.

 

 

 

[정리 ]

 

series의 구조는 1차원(one axis) => 행 또는 열.   => 인덱스명( 및 순번 )과 값으로 구성되어 있다.

 - > 인덱스명, 순번으로 조회가능. 방법 여러가지.

 

                                                                             

DataFrame의 구조는 2차원(0축, 1축)이다. => 0축 : 행 (인덱스명)  1축: 열 (컬럼명) 

 

- 인덱스 행 조회 : 인덱스명, 순번으로 조회가능

                   - 록(인덱스명) 조회

                   - 아이록(순번) 조회

                              => 한 행이면 시리즈 반환. series의 index = df 컬럼명

                              => 여러 행(펜시). DF 반환

 

                  - 대괄호에 인덱스, 슬라이싱하면 행 조회 (컬럼 열 조회 아님!)

 

- 컬럼 열 조회 : 컬럼명으로만 조회가능. 순번으로 조회불가능. df.colums를 이용해 index변수로 뽑아 조회가능

                   - 대괄호 조회

                         => 한 행이면 시리즈 반환.  series의 index =  df 인덱스명

                         => 여러 행(펜시). DF 반환

 

                   - 대괄호 조회  슬라이싱 . 인덱싱 .   -> 인덱스 행 조회로 인식


                   - 메소드 조회  

                          filter()   매개변수 : items,  like,   regex

 

 

- 특정 values 값 조회 : (행, 열)

                   - loc(이름)조회 (콤마 기준으로)

                   - iloc(순번) 조회 (콤마 기준으로)

                   -  grade.loc['id-2']['영어']  이렇게는 잘 안쓴다.

 

- boolean indexing

            - 조건 : bool series 

            - 조건을 인덱스 값으로 넣어서 (보통 행 조회)

                 -   DataFrame객체[조건]      # 컬럼 별이 아니라, 각 행마다 True 인 행을 반환
                 -   DataFrame객체.loc[조건]

 

 

2차원 자료구조 DataFrame의 조회결과는

=> 컬럼별, 인덱스별 => series 또는 DataFrame 반환

          -> 인덱싱, 슬라이싱, 펜시인덱싱(다중) 조회로 하나씩 뽑을 수 있다.

          -> 조회한 값 시리즈나 데이터프레임에 대해 또 메소드나 연산이나 처리 할 수 있다. 

               ex) movie_df.select_dtypes(exclude=['int64','float64']).info()

 

- DF의 한 컬럼(열)/ 한 인덱스(열) 을 조회할 경우 
   => series 로 반환.

이렇게 조회한 결과들에 대해 메소드 등 처리가 가능하다.


- DF의 여러 컬럼, 여러 인덱스 의 값을 조회할 경우 => Fancy indexing : 조회할 컬럼들을 리스트로 묶어서 전달
    => DataFrame 로 반환.

이렇게 조회한 결과들에 대해 메소드 등 처리가 가능하다.

 

 

- 내가 편한 방법 정하기 -

  • 컬럼명 조회할 때는 대괄호 또는 filter.
  • 인덱스명 조회할 때는 loc 쓰자.