728x90
반응형

지금까지 Index와 위치를 이용해서 데이터를 조회하는 방법에 대해 알아보았다. Index, 위치를 이용하여 행을 조회하는 것이 가장 빠르지만, 현실적으로 내가 원하는 데이터의 Index와 행의 위치를 미리 아는 것은 불가능하므로 이번 포스팅에서는 특정 조건으로 내가 원하는 행을 찾아내는 방법에 대해 학습해보도록 하겠다.

 

 

 

Pandas와 Boolean

불리언(Boolean)은 논리 자료형이라고도 하며, 참(True)과 거짓(False)을 나타낼 때 사용된다. Python에서 참(True)은 1, 거짓(False)은 0의 정수 값을 가지며, 이 특성을 잘 활용하면 재밌는 코드를 많이 만들어낼 수 있다.

>>> print(f"True의 Type: {type(True)}")
>>> print(f"False의 Type: {type(False)}")
>>> print("----"*10)
>>> print(f"True를 수치로 표현 시: {int(True)}")
>>> print(f"False를 수치로 표현 시: {int(False)}")
>>> print("----"*10)
>>> print(f"True를 수치로 표현 시: {float(True)}")
>>> print(f"False를 수치로 표현 시: {float(False)}")
True의 Type: <class 'bool'>
False의 Type: <class 'bool'>
----------------------------------------
True를 수치로 표현 시: 1
False를 수치로 표현 시: 0
----------------------------------------
True를 수치로 표현 시: 1.0
False를 수치로 표현 시: 0.0

Pandas는 Boolean Series를 이용하여 True인 행은 출력하고, False인 행은 출력하지 않을 수 있다. 이를 더 쉽게 이야기해보면, "내가 원하는 행만 True로 만들면 그 행만 조회할 수 있다"는 것이다.

 

 

 

 

1. 예제 데이터와 라이브러리 가지고 오기

※ 예제 데이터

이번 포스트에서도 지금까지 사용한 "시험점수.csv" 파일을 예제 데이터로 사용해보도록 하겠다.

사용할 라이브러리는 pandas지만, pandas와 함께 다니는 친구인 numpy도 혹시 쓸 일이 있을지 모르니 가져와주도록 하자.

시험점수.csv
0.00MB

 

>>> import pandas as pd
>>> import numpy as np

>>> FILE_PATH = "시험점수.csv"
>>> 시험점수 = pd.read_csv(FILE_PATH, encoding="euckr")
>>> 시험점수

  • 해당 예제 데이터는 이름, 성별, 학년, 반, 국어, 수학, 영어, 사회, 과학 총 9개의 열과 80개의 행으로 구성되어 있다.
  • 한글이 깨지는 경우, 위 코드처럼 pd.read_csv(File_path, encoding='euckr')로 불러오면 된다.

 

 

 

 

2. Series와 Boolean

  • DataFrame에서 조회할 대상을 가정해보자.

  • 조회할 대상: 3학년이고 2반에 있으며, 국어 점수가 70점 이상인 여학생을 찾는다.

  • 위 대상에 해당하는 속성이 4개나 되므로, 한 번에 찾기는 쉽지 않다.
  • 위 문구를 구성하는 조건을 최소 단위로 쪼개보자.

  • 조건 1: 학년 == 3
  • 조건 2: 반 == 2
  • 조건 3: 국어 >= 70
  • 조건 4: 성별 == "여자"

  • 문구를 최소 단위로 쪼개 보니 꽤 단순해졌다!
  • 방금 정의한 "조회할 대상"은 위 조건 4개에 대해 모두 참(True)인 행이다.
  • 즉, 위 조건 4개에 대해 모두 True인 행을 표현만 할 수 있다면, 위 행에 해당하는 사람의 데이터만 가지고 올 수 있다는 것이다.
  • 지금까지 우리는 Pandas에서 다양한 변수를 담고 있는 데이터(다변량 데이터) 타입인 DataFrame을 다뤄봤는데, 이번엔 단 하나의 변수만 담고 있는 데이터(단변량 데이터) 타입인 시리즈(Series)로 접근을 해보도록 하자.

 

 

 

2.1. 단변량 데이터를 담는 시리즈(Series)

  • 시리즈는 데이터 프레임에서 하나의 컬럼만 뽑으면 쉽게 만들 수 있다.
  • 데이터 프레임 "시험점수"에서 "성별" 시리즈를 뽑아보자.
>>> 시험점수["성별"]
0     남자
1     남자
2     남자
3     남자
4     남자
      ..
75    여자
76    여자
77    여자
78    여자
79    여자
Name: 성별, Length: 80, dtype: object
  • 시리즈는 각 Value에 대한 Index 정보, 시리즈의 이름(Name), 시리즈를 구성하는 원소의 수(Length), 시리즈의 데이터 타입(dtype) 정보를 담고 있다.
  • 이를 하나의 변수만 담고 있는 데이터 프레임이라고 생각해도 큰 문제는 없다.
    • 시리즈는 데이터 프레임에서 사용 가능한 함수의 대부분을 지원하므로, 데이터 프레임을 쓸 줄 안다면 큰 어려움 없이 익숙해질 수 있다.
    • 단, "시리즈 = 하나의 변수만 담긴 데이터 프레임"은 절대 아니다! 주의하도록 하자!
  • 시리즈는 DataFrame을 만들었던 방법처럼 list나 numpy array 등을 이용해 쉽게 만들 수 있다.
>>> Test_list = ["감", "바나나", "포도", "딸기"]
>>> pd.Series(data=Test_list, name="과일")
0      감
1    바나나
2     포도
3     딸기
Name: 과일, dtype: object

 

 

 

 

3. Boolean Series를 이용하여 원하는 행을 조회하기.

3.1. 단변량 데이터인 시리즈에 조건 걸기

  • "시험점수" 데이터 프레임에서 "성별" 시리즈를 뽑고, "여자"인 대상을 찾아보자.
  • Python은 기본적으로 다음과 같은 비교 연산자를 제공한다.
같다 다르다 크다 작다 이상 이하
기호 == != > < >= <=
  • 위 비교 연산자를 이용하여 "성별" == "여자"인 대상자를 찾아보자.
>>> 시험점수["성별"] == "여자"
0     False
1     False
2     False
3     False
4     False
      ...  
75     True
76     True
77     True
78     True
79     True
Name: 성별, Length: 80, dtype: bool
  • 비교 연산자를 사용하자 True와 False로 이루어진 Series가 출력되었다.
  • 이 Series에서 True는 "성별" == "여자"인 행을 뜻하며, False는 "성별" != "여자"인 행을 뜻한다.
  • 위에서 생성한 Boolean 시리즈를 이용해서, 제대로 탐색을 하였는지 확인해보도록 하자.
>>> 시험점수[시험점수["성별"] == "여자"].head(10)

  • 출력되는 결과가 매우 길어 df.head(n) 함수를 이용해 상위 n개의 행만 출력되게 하였다.
  • Pandas의 데이터 프레임은 df[Boolean Series]를 하면, Boolean Series에서 True에 해당하는 행만 출력한다.
  • 앞서, Boolean은 True는 1, False는 0의 값을 갖는다고 하였는데, 이 성질을 이용하면 "성별"=="여자"인 대상의 수를 알 수 있다.
>>> sum(시험점수["성별"] == "여자")
40
  • sum()은 괄호 안의 list, array, series 등의 Data type에 대해 합계를 내주는 함수로, 40이 나왔으므로 1이 40개 있다는 것을 보여준다.
  • 이는 "성별"=="여자"인 행이 40개 있다는 것으로, 여성의 수가 40명이라는 것을 의미한다.
  • 등호가 돌아가는 원리를 알았으니 이번엔 부등호를 조건으로 걸어보자.

 

  • 이번엔 부등호로 조회를 해보자.
  • 이번에는 국어 점수가 70점 이상인 대상을 찾아보자.
>>> 시험점수[시험점수["국어"] >= 70].head(10)

  • 국어 점수가 70점 이상인 상위 10명을 뽑아 보았다.
  • 부등호도 등호와 마찬가지로 쉽게 뽑을 수 있다.

 

 

 

 

3.2. 동시에 2개 이상의 조건 걸기

  • 앞서 시리즈를 이용해 단변량 데이터에 대해 조건을 걸어보았다.
  • 이번엔 2개의 시리즈를 동시에 사용하여 다변량 데이터에 대한 조건을 걸어보도록 하겠다.
  • 이때 사용되는 것이 옛날에 배웠던 집합(Set)이다.
  • Python에서 주로 사용되는 집합은 교집합, 합집합, 차집합이며, 이들은 다음과 같은 기호를 통해 사용할 수 있다.
집합 교집합 합집합 차집합
기호 & | -
  • 2개의 Boolean Series를 가지고 와보자.
>>> 여자_Boolean_Sr = 시험점수["성별"] >= "여자"
>>> 국어_Boolean_Sr = 시험점수["국어"] >= 70

>>> print(여자_Boolean_Sr)
>>> print("----"*10)
>>> print(국어_Boolean_Sr)
0     False
1     False
2     False
3     False
4     False
      ...  
75     True
76     True
77     True
78     True
79     True
Name: 성별, Length: 80, dtype: bool
----------------------------------------
0      True
1     False
2      True
3      True
4      True
      ...  
75    False
76     True
77    False
78    False
79     True
Name: 국어, Length: 80, dtype: bool
  • 두 Boolean 시리즈를 교집합 해보자.
>>> 여자_Boolean_Sr & 국어_Boolean_Sr
0     False
1     False
2     False
3     False
4     False
      ...  
75    False
76     True
77    False
78    False
79     True
Length: 80, dtype: bool
  • 두 시리즈 모두 True인 행만 True로 나오고, 둘 중 하나라도 False인 행은 False가 되었다.
  • 교집합은 두 가지에 모두 해당해야 한다는 의미이므로, 모두 True인 대상을 가지고 온다.
  • 즉, 두 조건에 동시에 해당하는 행만 교집합 시, True로 출력된다.
>>> 시험점수[여자_Boolean_Sr & 국어_Boolean_Sr].head(10)

  • 이를 이용하면, 조건이 아무리 많다고 할지라도 내가 원하는 대상을 구체적으로 찾아낼 수 있다.
  • 남은 조건인 "학년"==3, "반"==1을 추가하여 앞서 선언한 "조회할 대상"을 찾아보자.
>>> 시험점수[
        (시험점수["성별"] == "여자") &
        (시험점수["학년"] == 3) &
        (시험점수["반"] == 1) &
        (시험점수["국어"] >= 70)
        ]

  • 꽤 복잡한 조건이었음에도 Boolean Series를 사용하여 쉽게 찾아내었다.
  • 2개 이상의 Boolean Series를 변수에 담지 않고 바로 조회하려면 꼭 괄호 안에 넣어주기 바란다(괄호 미사용 시 에러 발생).

 

 

 

 

지금까지 조건에 해당하는 행 조회 방법에 대해 알아보았다. 다음 포스트에서는 Pandas의 str을 이용하여, 원하는 문자열에 해당하는 행을 탐색하는 방법에 대해 다뤄보도록 하겠다.

728x90
반응형
728x90
반응형

얼마만의 포스팅인지... 가장 최근에 한 포스팅이 2021년 05월 17일이니, 반년 조금 넘는 기간 동안 포스팅을 안 했다.

나름의 변명이라면 올해 4월에 새로운 직장에 가고, 프로젝트를 하나 둘 맡아서 하다 보니 정신이 없기도 했고, 프로젝트를 어느 정도 마무리 짓고 여유가 나자 그놈의 디아블로 2가 나와버리는 바람에 시간이 슉 지나가버렸다.

너무도 감사하고, 죄송스럽게도 많은 분들께서 찾아와 주셔서, 미약한 실력이나마 도움이 될 수 있기를 바라며 다시 한번 포스팅을 해보고자 한다. 과연, 포스팅하고자 했던 것들을 전부 올리고, 새로운 영역을 파헤쳐 갈 수 있을까?

 

 

 

 

데이터 프레임, 데이터 조회하기

Python을 사용하는 데이터 분석가에게 가장 기초가 되는 Pandas를 다룬 것이 올해 초인 2021.02.24일이었으니, 다음에 뭘 다루려 했었는지 가물가물하다. 앞서 DataFrame의 Index와 Column명을 가지고 노는 법에 대해 알아봤으니, 이번 포스팅에서는 Index와 Column명을 이용해서 내가 원하는 데이터만 가지고 오는 법에 대해 알아보도록 하겠다.

데이터 프레임의 가장 큰 장점은 누구든지 이해하기 쉬운 형태로 데이터를 볼 수 있다는 것이지만, 데이터의 양이 많아질수록 한눈에 들어오지 않을 정도로 데이터가 거대해지기 때문에, 내게 필요한 데이터만 조회하는 법을 알아야 한다.

데이터 프레임의 조회 방식은 크게 index와 column 명으로 조회하는 방법, 데이터의 순서를 기반으로 조회하는 방법,  Boolean으로 조회하는 방법이 있는데, 이를 찬찬히 알아보도록 하자.

 

내가 원하는 데이터를 가지고 오기

  • 내가 원하는 데이터를 가지고 오는 방법은 크게 3 가지가 있다.
  1. 내가 원하는 행을 가지고 오기
  2. 내가 원하는 열을 가지고 오기
  3. 내가 원하는 행과 열을 가지고 오기
  • 여기서 내가 원하는 행을 가지고 오는 방법이 비교적 복잡하며, 원하는 행을 가지고 온 후 내가 필요한 열을 설정해주면, 문제는 쉽게 해결된다.
  • 그러므로, 행을 가지고 오는 방법을 위주로 다뤄보도록 하자.
  • Pandas의 DataFrame에서 내가 원하는 행을 가지고 오는 방법도 크게 3가지가 있다.
  1. Index를 이용해서 가지고 오기(loc)
  2. 위치를 이용해서 가지고 오기(슬라이싱, iloc)
  3. 조건을 이용해서 가지고 오기(Boolean)
  • 이번 포스트에서는 Index를 이용해 내가 원하는 데이터를 가지고 오는 방법에 대해 다뤄보도록 하자.

 

 

 

 

1. 예제 데이터 가지고 오기

※ 예제 데이터

해당 예제 데이터는 이름, 성별, 학년, 반, 국어, 수학, 영어, 사회, 과학 총 9개의 열(Column)과 80개의 행(Row)으로 구성된 csv파일이다. 당분간 이 데이터로 학습을 진행해보도록 하자.

시험점수.csv
0.00MB

  • 다운로드 받은 위 예제 데이터("시험점수.csv")파일을 내 워킹 디렉토리(Working Directory)로 이동시키거나, 파일의 경로를 이용해서 불러와보도록 하자.
>>> import pandas as pd
>>> import numpy as np

>>> FILE_PATH = "시험점수.csv"
>>> 시험점수 = pd.read_csv(FILE_PATH, encoding="euckr")
>>> 시험점수

  • R과 비교되는 파이썬의 가장 큰 장점은 한글 사용이 비교적 자유롭다는 것이다.
  • 파이썬은 utf-8 기반으로 만들어져 있기 때문에 데이터뿐만 아니라 변수명을 한글로 써도 큰 문제가 없다.
  • 혹시 모르는 에러가 발생할 위험이 있으므로, 그래도 영어를 사용하는 것을 추천한다!!
  • 한글이 들어 있는 파일이라면 파일의 경로만을 이용해서 데이터를 가져오는 경우, 한글이 깨지는 경우가 있는데, 이는 대부분 Encoding 문제로, pd.read_csv() 함수의 encoding 파라미터를 "euckr"로 지정하면 거의 해결된다.

 

 

 

 

2. Index를 이용해서 데이터를 가지고 오기.

  • 데이터 프레임에서 내가 원하는 행을 조회하는 가장 빠른 방법은 Index를 이용하는 것이다.
    • Index는 유일하게 존재하는 고유한 값일 수도 있으나, 중복된 값일 수도 있다.
    • Index를 이용한다면, 데이터 조회뿐만 아니라 데이터 병합(Merging)도 쉽게 할 수 있다.
  • Index로 조회하는 방법은 다음과 같다.
  • df.loc[index]: index에 해당하는 DataFrame의 행을 가지고 온다.

 

 

2.1. 하나의 index를 가지고 와보자.

  • index 60번을 가지고 와보자.
>>> 시험점수.loc[60]
이름    민준
성별    남자
학년     4
반      1
국어    90
수학    75
영어    80
사회    70
과학    60
Name: 60, dtype: object

>>> type(시험점수.loc[60])
pandas.core.series.Series
  • 하나의 index를 조회하자, Series Type으로 해당 index 정보가 조회되는 것을 볼 수 있다.
  • 이 시리즈에서 이름을 하나의 값으로 가지고 와보도록 하자.
>>> Index60_Sr = 시험점수.loc[60]
>>> Index60_Sr["이름"]
'민준'
  • 파이썬의 딕셔너리(Dictionary) 객체처럼 내가 원하는 변수명을 key로 주니, 내가 원하는 값이 반환되는 것을 볼 수 있다.

 

 

 

 

2.2. 여러 개의 index를 가지고 와보자.

  • 이번에는 여러 개의 index를 한 번에 가지고 와보도록 하자.
  • 15, 20, 30, 45번의 Row를 가지고 와보도록 하겠다.
  • 여러개의 index를 한번에 조회는 내가 원하는 index들이 들어있는 list를 만들어 loc에 넣으면 된다.
>>> 시험점수.loc[[15,20,30,45]]

  • 이전과 다르게 이번에는 index에 해당하는 데이터 프레임으로 결과가 조회되는 것을 볼 수 있다.
  • 위 방법을 응용하면 Index A부터 Index B까지 조회도 가능하다.
>>> index_range = range(15,20) 
>>> 시험점수.loc[index_range]

>>> 시험점수.loc[15:20]

  • 다만 Index의 범위를 이용하여 탐색하는 방법은 위 방법보다 다음에 다룰 Slicing이 더 많이 사용되므로, 이런 것도 있구나~ 하고 넘어가도록 하자.

※ 주의 사항

  • 일반적인 파이썬 슬라이싱 방식은 start:end 일 경우, start부터 end-1까지의 연속된 값을 반환하나, .loc[start:end]는 start 부터 end 까지의 연속된 index를 조회한다.
시험점수[15:20]

  • 일반적인 슬라이싱 방식은 위 방식으로 하며, DataFrame.loc[Index]는 Index에 속해 있는 모든 index의 행을 가지고 온다.

 

 

 

 

2.3. index와 column으로 조회해보자.

  • 해당 Index에서 특정 Column의 데이터만 보고 싶다면, index와 column을 동시에 넣어 조회하면 된다.
  • 앞서 소개한 df.loc[index]를 아래와 같이 쓰면 된다.
    • df.loc[index, column]
  • 16번 index의 국어 점수를 조회해보자.
>>> 시험점수.loc[16, "국어"]
75
  • 해당 방법을 통해 내가 필요한 값을 하나의 원소로 출력하였다.
  • 이번에는 index 16의 이름, 학년, 반, 국어 점수를 동시에 출력해보도록 하자.
>>> 시험점수.loc[16, ["이름", "학년", "반", "국어"]]
이름    정숙
학년     1
반      2
국어    75
Name: 16, dtype: object
  • 내가 필요한 index들을 list에 담아 조회하였듯, 조회하고자 하는 column들을 list에 넣어 조회하면 해결된다.
  • 이번엔 index를 16, 20, 25로 column을 이름, 학년, 반, 국어로 조회해보자.
>>> 시험점수.loc[[16, 20, 25], ["이름", "학년", "반", "국어"]]

 

 

 

 

2.4. 값을 Index에 넣어 조회해보자.

  • 앞서 다뤘던 방법들은 내가 원하는 Index를 알고 있다는 전제하에 유용하지만, 대부분 Index는 자동으로 설정되는 0~n 사이의 값이므로 이를 활용하는 것은 쉽지 않다.
  • 이럴 땐, 특정 열을 Index로 만들어 조회하는 것으로 이 문제를 해결할 수 있다.
  • "이름" column을 Index로 만들어보자.
  • df.set_index(column, drop=True, inplace=False): column을 df의 index로 설정한다.
>>> 시험점수.set_index("이름", inplace=True)
>>> 시험점수

  • inplace = True로 설정하면, df.set_index의 대상인 df에 바로 이를 적용할 수 있다.
  • default인 inplace를 False로 하면 df.set_index의 결과만 출력한다.
  • drop=False로 설정하면, 기존 index를 제거하지 않고 데이터 프레임의 열로 추가한다.
  • index를 "영철"로 조회해보자.
>>> 시험점수.loc["영철"]

  • DataFrame의 Index는 고유한 값이 아니어도 설정 가능하므로, 위와 같이 "이름"이 "영철"에 해당하는 Row를 모두 가지고 오는 것을 볼 수 있다.
  • Index를 초기 상태로 돌려보자.
>>> 시험점수.reset_index(drop=False, inplace=True)
>>> 시험점수

  • 이번에는 학년이 1학년인 사람들만 조회해보도록 하자.
>>> 시험점수.set_index("학년", inplace=True)
>>> 시험점수.loc[1]

 

 

 

 

2.5. 다중 값을 Index로 조회해보자.

  • 지금까지 하나의 열만 Index로 넣어 조회를 해보았다.
  • 그렇다면, 여러 개의 열을 Index에 넣어 내가 원하는 행만 조회할 수는 없을까?
  • 이때는 크게 2가지 방법이 있다.
  1. Multi Index를 만들어 조회하기
  2. 조회를 위한 열을 만들기
  • 먼저 Multi index를 만드는 법부터 알아보도록 하자.
  • Index를 다시 초기화하고 학년과 반으로 Multi index를 만들어보도록 하겠다.
>>> 시험점수.reset_index(drop=False, inplace=True)
>>> 시험점수.set_index(["학년", "반"], inplace=True)
>>> 시험점수

  • 2학년 1반 사람들을 조회해보도록 하자.
  • Multi Index는 Python의 Tuple로 생성되므로, Tuple로 조회하면 된다.
>>> 시험점수.loc[(2,1)]

  • 3개 이상의 열을 Multi Index로 만들어 조회도 가능하다.
  • 이번에는 학년, 반, 이름으로 Multi Index를 만들어보자.
>>> 시험점수.reset_index(drop=False, inplace=True)
>>> 시험점수.set_index(["학년", "반", "이름"], inplace=True)
>>> 시험점수

  • 이번에는 2학년 1반의 영철을 조회해보도록 하자.
>>> 시험점수.loc[(2,1,"영철")]
성별     남자
국어    100
수학     80
영어     75
사회     80
과학     45
Name: (2, 1, 영철), dtype: object
  • 위와 같은 방법을 통해 내가 원하는 Column을 Index로 만들어 조회해보았다.
  • 다만, 해당 방법의 한계점은 특정한 하나의 값만 조회가 가능하므로, 수학 점수와 같은 연속형 데이터의 범위에 대해서는 조회가 불가능하다는 단점이 있다.
  • 물론, 이용해 우회하여 해결할 수 있기는 하다.

 

 

 

 

2.6. 새로운 열을 만들어 조회하기

  • 지금까지는 기존에 존재하는 열을 그대로 Index로 만들어 조회를 하였다.
  • 이번에는 내가 필요로 하는 값에 대한 변수를 만들고, 이 변수를 Index로 만들어 조회를 해보도록 하겠다.
  • 수학 점수가 70점 이상인 사람들을 표시하는 새로운 변수를 만들어보자.
    • 조건을 이용한 새로운 변수 만들기는 추후 자세히 다룰 테니 이번엔 단순 참고용으로 보도록 하자.
>>> 시험점수["수학_mask"] = np.where(시험점수["수학"] >=70, "수학_70점_이상", "수학_70점_미만")
>>> 시험점수

  • 70점 이상은 "70점_이상", 70점 미만은 "70점_미만"인 수학_mask"라는 변수를 생성하였다.
  • 새로 만든 "수학_mask"변수를 이용해서 70점 이상인 사람들만 출력해보도록 하자.
>>> 시험점수.set_index("수학_mask", inplace=True)
>>> 시험점수.loc["수학_70점_이상"]

  • 이미지가 너무 커서 일부만 표시해보았다. 길이가 48인 결과가 나왔다면, 제대로 나온 것이다.
>>> len(시험점수.loc["수학_70점_이상"])
48
  • 이번엔 영어 점수가 70점 이상인 사람을 추가해보자.
>>> 시험점수.reset_index(drop=False, inplace=True)
>>> 시험점수["영어_mask"] = np.where(시험점수["영어"] >=70, "영어_70점_이상", "영어_70점_미만")
>>> 시험점수

  • 이번엔 수학 점수가 70점 이상이면서, 영어 점수도 70점 이상인 사람을 출력해보자.
  • Multi Indexing을 사용할 수도 있으나, 이번에는 수학_mask와 영어_mask를 하나로 합쳐서 Index를 만들어보겠다.
>>> 시험점수["key"] = 시험점수["수학_mask"] + "&"+ 시험점수["영어_mask"]
>>> 시험점수.set_index("key", inplace=True)
>>> 시험점수.loc["수학_70점_이상&영어_70점_이상"]

  • 이미지가 너무 커서 일부만 표현하였으며, 길이가 35가 나오면 정상이다.
>>> len(시험점수.loc["수학_70점_이상&영어_70점_이상"])
35
  • 위와 같은 새로운 변수를 만들어 Index로 바꾸는 방법은 이해를 돕기 위해 변수를 지저분하게 만들었지만, 이보다 깔끔하게 할 수 있는 방법을 다음에 포스팅해보도록 하겠다.

 

 

 

지금까지 Index를 이용한 데이터 프레임 행 조회 방법에 대해 알아보았다. 다음 포스트에서는 위치를 이용한 행 조회에 대해 알아보도록 하겠다.

728x90
반응형
728x90
반응형

 이전 포스트에서 DataFrame의 생김새와 부위별 이름에 대해 알아보았다. DataFrame의 가장 큰 특징은 index가 존재한다는 것이고, 이 index를 얼마나 잘 가지고 노느냐에 따라 DataFrame을 얼마나 효율적으로 사용할 수 있는지가 나뉘게 된다.

 

 

데이터 프레임과 인덱스

 Pandas에 대해 흔히들 가지고 있는 오해가 Pandas는 순차적으로 데이터를 조회하기 때문에, 데이터 전처리 속도가 매우 느리다는 것이다.

 이 말은 반은 맞고, 반은 틀리다고 할 수 있는데, DataFrame에서 특정 데이터를 단순하게 조회하면, 순서대로 하나하나 조회하기 때문에 속도가 매우 느려지고, 도리어 이 특징을 이용해서, 데이터 전처리 속도를 줄일 수도 있다.

 그러나, 인덱스를 사용하여 조회를 하게 된다면, 순차적 조회가 아닌 한 번에 index에 해당하는 값을 가지고 오기 때문에 조회 속도가 엄청 빨라진다.

 그러므로, Pandas를 사용해야 하는 데이터 분석가라면 반드시 이 인덱스를 잘 가지고 놀 수 있어야 한다.

 

 

 

 

1. DataFrame 생성 시, 원하는 Index 부여하기

  • index는 DataFrame을 생성하면서 부여할 수도 있고, DataFrame을 생성한 후에도 바꿔줄 수 있다.
  • 다음과 같은 데이터 셋을 만들어보자.
import pandas as pd
name_list = ["박명수", "유재석", "노홍철", "길", "정준하", "정형돈", "하하"]
math_list = [65, 95, 70, 80, 100, 85, 60]
english_list = [75, 80, 85, 90, 65, 75, 100]
class_list = [1, 2, 1, 2, 2, 2, 1]
index_list = list(range(10, 24, 2))

exam = pd.DataFrame({"name":name_list, "math":math_list, "english":english_list,
                     "class":class_list}, index=index_list)
exam

  • range(start, end, by): start부터 end까지 값을 by 간격으로 만들 준비를 한다.
    (list 함수 같은 것으로 가동해주지 않으면, 대기 상태를 유지한다)
  • 생성된 데이터 프레임을 보듯, 데이터 프레임 생성 시, index 파라미터에 넣어준 list를 index로 부여한다.

 

 

 

 

2. 내가 원하는 칼럼을 index로 부여하기

  • 이미 index가 정해졌다 할지라도, index는 내가 원하는 칼럼을 index로 만들어줄 수 있다.
exam.set_index("name", inplace=True)
exam

  • DataFrame.set_index(column, drop=True, append=False, inplace=False): set_index()는 말 그대로, 내가 원하는 칼럼을 index로 설정해주는 함수다.
  • drop 파라미터는 기존 칼럼을 index로 넣을 때, 기존 칼럼을 말 그대로 버려버릴지를 묻는 것이다.
  • append 파라미터는 기존 인덱스에 내가 원하는 칼럼까지 추가해서 인덱스를 만들지를 묻는 것이다.
  • inplace 파라미터는 원본 데이터에 덮어씌울지를 물어보는 것이다. 여기서는 inplace = True를 하였으므로, index가 바뀐 것을 바로 원본에 적용하였다.
  • 중복되는 값이라 할지라도 index로 만들 수 있다.
exam.set_index("class", inplace=True)
exam

  • 데이터 프레임의 인덱스에 대해 "중복이 돼서는 안 되는 유니크한 값이어야 한다."라 오해를 하는 경우가 종종 있는데, 위에서 보시다시피 중복이 가능하다. 이는, 데이터 프레임의 인덱스의 특징이며, 이 특징을 잘 이용하는 것이 중요하다.
  • 데이터 프레임의 인덱스는 중복 가능하므로, 조회 시, 해당 인덱스에 해당하는 값을 모두 가지고 온다.
exam.loc[2]

  • DataFrame.loc[index]: index에 해당하는 행을 조회하는 방법으로 추후 자세히 다루도록 하겠다.

 

 

 

 

3. 인덱스 초기화

  • 무한도전 멤버들의 이름을 인덱스로 했었다가 class로 인덱스를 설정하니, 무한도전 멤버들의 이름이 사라져 버렸다.
  • 이는 DataFrame.set_index()는 기본적으로 기존 index를 없애는 것을 전재로 하기 때문이다.
  • 이러한 일을 막기 위해선 set_index()를 하기 전에 인덱스를 초기화해줘야 한다.
exam.reset_index(drop = False, inplace = True)
exam

  • DataFrame.reset_index(drop=False, inplace=False): reset_index는 인덱스를 말 그대로 초기화시켜버린다.
  • drop 파라미터는 기존의 index를 버릴지 말지를 결정하는 파라미터다
  • 무한도전 멤버들의 이름이 index인 상태에서 reset_index()하고 set_index()를 하였다면, 이번처럼 기존 인덱스가 날아가버리는 일을 막을 수 있다.

 

 

 

 

4. 새로운 list를 인덱스로 부여하고 인덱스를 조작해보자

  • 처음에 만들었던, name_list를 index로 부여하여, 무한도전 멤버의 이름이 index인 상태로 돌아가 보자.
exam.index = name_list
exam

  • DataFrame.index: DataFrame의 index를 조작할 수 있다.
  • 이전에는 index의 이름이 name으로 나왔으나, index는 본래 이름이 따로 없기 때문에 index의 이름이 없는 상태로 출력된 것을 볼 수 있다.

4.1. 인덱스 이름 부여

exam.index.name = "name"
exam

  • DataFrame.index는 뒤에 다른 함수들을 붙여 추가적인 기능들을 실행할 수 있다.
  • 이번에는 DataFrame.index.name으로 하여 index의 이름을 부여해보았다.

4.2. 인덱스 데이터 추출

>>> exam.index
Index(['박명수', '유재석', '노홍철', '길', '정준하', '정형돈', '하하'], dtype='object', name='name')
  • list를 index에 넣었듯, array로 index를 뽑아낼 수도 있다.
  • 이러한 index 조작은 데이터 프레임을 다룰 때, 상당히 쓸모 있는 기술이므로 꼭 숙지하도록 하자.

 

 

 

 

5. 멀티 인덱스(Multi index)와 인덱스를 기준으로 정렬

  • 멀티 인덱스는 말 그대로 index를 한 번에 여러 개 사용하는 방법이다.
  • 무한도전 멤버의 이름을 칼럼으로 되돌리고, class, name으로 멀티 인덱싱을 해보자.
exam.reset_index(drop=False, inplace=True)
exam.set_index(["class", "name"], inplace = True)
exam

  • 멀티 인덱스는 set_index(column)에서 칼럼을 여러 개 넣어서 실시할 수 있다.
  • 멀티 인덱스를 하고 나니, class 2의 길, 정준하, 정형돈의 class가 하나로 붙어 깔끔하게 나온 것을 볼 수 있다.
  • 그러나, 썩 깔끔해 보이지 않으므로 인덱스를 기준으로 정렬시켜보자.

5.1. 인덱스 기준 정렬

exam.sort_index(inplace=True)
exam

  • DataFrame.sort_index(ascending=True, inplace=False): 말 그대로 index순으로 정렬(sort)한다.
  • ascending 파라미터는 오름차순, 내림차순을 의미하며, 기본적으로 오름차순 정렬이 실행된다.

5.2. 멀티 인덱스의 실제 모습

  • 멀티 인덱스를 실행하게 되면, 데이터의 형태를 보다 쉽게 파악할 수 있다는 장점이 있다. 때문에 멀티 인덱스는 group_by를 하여 두 집단 이상의 기술 통계량을 볼 때, 멀티 인덱스로 출력되게 된다.
  • 멀티 인덱스를 하면, class는 하나의 index로 뭉친 것처럼 보이는데, 눈에만 저렇게 보이지 실제로는 따로 떨어져 있다.
>>> exam.index
MultiIndex([(1, '노홍철'),
            (1, '박명수'),
            (1,  '하하'),
            (2,   '길'),
            (2, '유재석'),
            (2, '정준하'),
            (2, '정형돈')],
           names=['class', 'name'])
  • exam의 index를 보면, 튜플로 묶여 있는 것을 볼 수 있다.

5.3. 멀티 인덱스 해제

exam.reset_index(drop=False)

  • 멀티 인덱스 해제는 reset_index()를 하여 쉽게 할 수 있다.

 

 

 

 지금까지 판다스에서 인덱스를 가지고 노는 법에 대해 학습해보았다. 판다스에서 인덱스를 얼마나 잘 활용하느냐에 따라 판다스의 속도는 크게 변하므로, 인덱스를 잘 활용하길 바란다.

728x90
반응형
728x90
반응형

 이전 포스트에서 데이터 프레임을 만들어보았으니, 이번에는 데이터 프레임의 부위별 이름을 알아보자.

 

 

데이터 프레임의 구조와 용어 정리

  • 위 표는 우리가 지금까지 봐온 데이터 프레임이다. 데이터 프레임의 생김새는 우리가 자주 봐왔던 표(Table)처럼 생겼다.
  • Data를 사용하는 분야에서 기본적으로 사용하는 관계형 데이터베이스(Relational Database, RDM)의 테이블(Table)도 데이터 프레임과 동일하게 생겼다.
  • RDB를 여기저기서 많이 사용하다 보니, 그 용어를 데이터 프레임에도 사용하는 경우가 많기 때문에, RDB에서 사용하는 용어도 함께 정리하도록 하겠다.

 

 

 

 

1. 칼럼(Column)

  • 칼럼(Column)은 단어 그대로 을 의미하며, 행과 열을 가진 데이터에서 열은 모두 칼럼이라고 불린다.
  • 변수(Variable), 속성(Attribute), 필드(Field)라고도 불린다.
  • 데이터에서 객체(대상)가 가지고 있는 특징이 들어간다.
  • 예를 들어, 이름, 성별, 나이와 같은 대상 집단이 가지고 있는 특징이다.
  • 차수(Degree): RDB에서는 칼럼의 수를 가리킨다.
    예) 위 테이블의 Degree는 11이다.
  • 도메인(Domain): RDB에서 한 칼럼에서 가질 수 있는 값의 집합
    예) 성별의 도메인은 "남", "여" 둘 뿐이며, 그 외의 값은 들어갈 수 없다.

 

 

 

 

2. 로우(Row)

  • 말 그대로 행을 가리키며, 데이터 하나하나를 의미한다. 그러다 보니, 모양이 데이터 프레임과 조금 다르더라도, 데이터 하나하나를 지칭할 때, 단순하게 Row라고 부르기도 한다.
  • 튜플(Tuple), 레코드(Record)라고도 불린다.
  • 데이터의 대상이 되는 객체 하나하나를 의미한다.
  • 예를 들어, 위 데이터 프레임에서 index가 417번인 사람은, 고객번호(PassengerId)가 1309번이고, 이름이 Peter, Master. Michael J이며, 성별이 male인 사람이다.
  • 카디널리티(Cardinality): 행의 총 개수이다.

 

 

 

 

3. 인덱스(Index)

  • 데이터 프레임만의 특징으로, index는 중복될 수도 있고, 동일한 index에 해당하는 row의 값이 다를 수도 있다.
  • index를 어떻게 조작하느냐에 따라, 데이터 프레임에서의 데이터 조회 속도 차이가 엄청 커진다.
  • RDB의 key와 유사해 보이지만, RDB의 key는 고유 개체를 식별할 수 있는 유니크한 값임에 반해, 데이터 프레임의 index는 중복이 가능하고, index가 동일하나, row에 있는 값은 다를 수 있으므로, key와 굉장히 다르다.

 

 

 

 지금까지 데이터 프레임의 행, 열의 다른 용어와 그것이 의미하는 바에 대해 간단히 다뤄봤다. 위 단어 외에도 인스턴스(Instance), 엔티티(Entity)와 같은 다양한 단어가 있으나, 데이터 프레임이던 테이블이던 기본적으로 행과 열이 중심이기 때문에 위 용어만 알면, 데이터에 대한 기본적인 의사소통은 할 수 있을 것이다.

 다음 포스트에서는 index를 가지고 노는 방법에 대해 학습해보도록 하겠다.

728x90
반응형
728x90
반응형

판다스(Pandas) 소개

 파이썬을 처음 사용하는 데이터 분석가가 제일 먼저 공부해야 할 라이브러리를 한 가지 꼽으라면, 많은 사람들이 판다스(Pandas)를 선택할 것이다.

 판다스는 R과 마찬가지로 데이터 프레임(DataFrame)을 사용해서, 데이터를 시각화, 분석을 할 수 있는데, R의 데이터 프레임이 그렇듯 매우 직관적이고, 데이터를 가지고 놀기 좋은 R의 기능을 대부분 사용할 수 있기 때문에 데이터 분석가에게 있어 필수 라이브러리라고 할 수 있다.

 

 사족으로 판다스라고 하면, 동물인 판다가 먼저 떠오를 텐데, 판다스는 동물에서 따온 이름이 아닌, 계량 경제학에서 사용하는 "패널 데이터(Panner Data)"에서 따온 이름이다.

 사회 과학에서 자주 다뤄지는 패널 데이터를 간략히 설명하자면, 횡단 데이터인 한 시점에서의 데이터 셋이 종단 데이터로 규칙적인 기간을 간격으로 여러 개 존재하는 데이터를 말한다. 즉, 종단 + 횡단의 성격을 갖는 데이터가 패널 데이터다. 이는 판다스가 한 시점에서 뿐만이 아닌 시계열 데이터에도 강한 면모를 가진다는 뜻이기도 하다.

 

 판다스는 대용량 데이터를 다룰 때나, 서비스를 위해 0.5초, 1초 내의 빠른 연산이 필요한 상황에선 취약한 모습을 보이기 때문에 만능이라고 할 수는 없으나, 판다스는 데이터의 흐름이나 데이터의 특징 파악이 매우 쉬우므로, 먼저 판다스로 코드를 짜고, 속도가 매우 빠른 Numpy로 코드를 수정하면, 이를 쉽게 해결할 수 있다.

 

 

 

 

1. 판다스의 데이터 타입

  • 판다스는 크게 2개의 고유 데이터 타입을 가지고 있다.
  • 하나는 데이터 프레임(DataFrame)이고, 다른 하나는 시리즈(Series)이다.
  • 어떻게 생겼는지만 간략히 봐보자.
import pandas as pd
from sklearn.datasets import load_iris

# 붓꽃(iris) 데이터를 가져와보자.
iris_dict = load_iris()

DF = pd.DataFrame(iris_dict["data"], columns=iris_dict["feature_names"])
DF

  • 위 표가 데이터 프레임이다.
  • 데이터 프레임은 마치 액셀처럼 이쁘게 표로 나눠져 있는 형태다.
  • 엑셀과 차이라면, 데이터 프레임은 모든 데이터를 한 번에 보여주지 않는다는 것이다.
  • 데이터 프레임은 한 번에 최대 60개 행까지 보여준다.
>>> DF[:60]

>>> DF["sepal length (cm)"]
0      5.1
1      4.9
2      4.7
3      4.6
4      5.0
      ... 
145    6.7
146    6.3
147    6.5
148    6.2
149    5.9
Name: sepal length (cm), Length: 150, dtype: float64
  • 시리즈는 array와 굉장히 비슷하며, 데이터 프레임은 길이가 동일한 시리즈가 열의 숫자만큼 붙어있다고 생각해도 좋다.
  • array와의 차이점은 array의 index는 무조건 0부터 시작하지만, 시리즈는 그렇지 않다는 것이다. 또한 데이터 프레임이나 시리즈는 멀티 인덱스라 하여, 2개의 칼럼을 인덱스로 사용할 수 있다.

 

 

 

 다음 포스트에서는 본격적으로 데이터 프레임을 다뤄보도록 하겠다.

728x90
반응형
728x90
반응형

 자, 드디어 마지막 기초 자료형인 DataFrame이다. DataFrame은 pandas의 대표적인 Type이며, R을 공부해 본 사람이라면, 상당히 친숙하게 느껴지는 단어일 것이다.

 pandas의 DataFrame은 R의 Dataframe을 Python에서도 사용해보기 위해 만들어졌으며, R에서 할 수 있는 대부분의 기능을 판다스에서도 구현할 수 있다.

 이번 포스트에서는 데이터 분석가들의 필수 Type인 DataFrame이 어떻게 생겼는지와 아주 대략적인 대표 기능만 살펴보고 바로 넘어가도록 하자.

 

 

 먼저 DataFrame을 만들어보자.

  • DataFrame을 만드는 방법은 크게 2가지가 있다.
    1.  길이가 동일한 list들을 컬럼 하나하나에 배정하는 방법
    2. M*N 행렬 형태의 Data(Array, Tupple)를 DataFrame에 넣는 방법
# pandas 모듈을 가지고 오자
>>> import pandas as pd
>>> import numpy as np


# 1. 길이가 동일한 list들을 DataFrame에 넣어보자
# DataFrame에 들어갈 길이가 같은 list들을 만들자
>>> name = ["민철", "기훈", "재성", "현택", "윤기"]
>>> math = [40, 60, 80, 75, 65]
>>> english = [75, 80, 65, 80, 70]
>>> science = [85, 70, 75, 80, 60]

# list들을 이용해서 DataFrame을 만드는 경우는 다음과 같다
>>> DF = pd.DataFrame({"name":name, "math":math, "english":english, "science":science})
>>> DF

name	math	english	science
0	민철	40	75	85
1	기훈	60	80	70
2	재성	80	65	75
3	현택	75	80	80
4	윤기	65	70	60



# 2. array를 이용해서 DataFrame을 만들어보자.
# 10, 100 사이의 임의의 값으로 만들어진 행렬을 생성하자
>>> row_number = 50
>>> score_mat = np.random.randint(10, 100, size=(row_number, 4))

# ID를 만들어보자
>>> ID_list = []
>>> for i in range(row_number):
    
	    ID = "A" + str(i)
    	ID_list.append(ID)
    
# shape을 맞춰서 ID_array와 score_mat을 병합시켜보자
>>> ID_array = np.array(ID_list)
>>> ID_array = ID_array.reshape((50, 1))

>>> data_array = np.hstack((ID_array, score_mat))

# array를 DataFrame을 만들어보자
>>> DF2 = pd.DataFrame(data_array, columns=["ID", "math", "English", "science", "Korean"])
# 생성한 DataFrame의 상위 10개만 출력해보자
>>> DF2.head(10)


ID	math	English	science	Korean
0	A0	35	38	62	51
1	A1	52	29	40	93
2	A2	28	16	99	71
3	A3	93	42	61	48
4	A4	23	60	39	48
5	A5	93	96	16	55
6	A6	13	69	88	90
7	A7	31	18	80	30
8	A8	59	12	66	93
9	A9	54	70	57	38
  • DataFrame을 처음 보면 마치 엑셀에서 우리가 일반적으로 만들던 표랑 굉장히 유사하다는 것을 알 수 있다.
  • DataFrame에는 각 열(Column)별로 동일한 데이터 타입을 넣을 수 있다.
  • pd.DataFrame() 함수를 통해 DataFrame을 만들 수 있다.
  • np.random.randint(시작 값, 끝 값, 형태) 함수는 시작 값, 끝 값 사이에서 랜덤한 값이 담긴 array를 생성한다.
  • np.hstack((array1, array2)) 함수는 두 array를 열을 기준으로 병합한다.
  • DataFrame.head(숫자) 함수는 내가 숫자만큼 DataFrame을 출력한다.

 

 

DataFrame의 컬럼별 dtype을 확인해보자

# DataFrame의 data type을 확인해보자
>>> DF2.dtypes
ID         object
math       object
English    object
science    object
Korean     object
dtype: object


# math, English, science, Korean 컬럼을 정수 type으로 바꿔보자
>>> DF2["math"] = DF2["math"].astype("int64")
>>> DF2["English"] = DF2["English"].astype("int64")
>>> DF2["science"] = DF2["science"].astype("int64")
>>> DF2["Korean"] = DF2["Korean"].astype("int64")
>>> DF2.dtypes
ID         object
math        int64
English     int64
science     int64
Korean      int64
dtype: object
  • DataFrame.dtypes 함수를 통해 DataFrame의 각 컬럼들의 Type을 확인할 수 있다.
  • DataFrame["컬럼"].astype("바꿀 dtype") 함수를 통해 DataFrame의 해당 컬럼 dtype을 바꿀 수 있다.

 

 

DataFrame을 Slicing 해보자.

# 10번 row부터 20번 row까지 출력해보자
>>> DF2[10:20]
	ID	math	English	science	Korean
10	A10	78	24	99	79
11	A11	41	87	83	10
12	A12	61	71	31	78
13	A13	74	80	32	99
14	A14	20	19	95	38
15	A15	24	67	22	24
16	A16	39	53	41	82
17	A17	34	57	52	67
18	A18	34	60	27	73
19	A19	27	35	91	81




# 수학 80점 이상인 Row만 출력해보자
>>> DF2[DF2["math"] >= 80]
	ID	math	English	science	Korean
2	A2	90	70	70	72
4	A4	90	27	64	42
8	A8	99	21	71	92
9	A9	89	61	11	30
28	A28	81	29	27	86
32	A32	84	19	89	31
44	A44	97	73	36	78
45	A45	80	95	54	12
48	A48	86	19	99	83
  • pandas의 dataFrame은 Numpy의 array와 동일한 방법으로 Slicing 할 수 있으며, 내가 원하는 조건에 대한 Row도 쉽게 가져올 수 있다.

 

 

 이번 포스트에서는 DataFrame에 대해 아주 간략하게 훑어만 봤는데, 설명을 보다 보면 설명이 지나치게 부족하지 않는가? 하는 생각이 들 것이다. 

 pandas의 DataFrame 역시 Numpy의 array와 마찬가지로 그 영역이 매우 크기 때문에 따로 카테고리를 만들어서 세세하게 설명하고자 한다.

 이번 포스트에서는 맛보기로 DataFrame이 어떻게 생겼는지만 인식하는 수준에서 끝내고, 추후 Python-pandas 카테고리의 포스트에서 pandas의 각 기능들을 세세하게 따져보도록 하겠다.

 
728x90
반응형
728x90
반응형

데이터 프레임(Data Frame)

지난 포스트에선 데이터프레임의 생성과 데이터프레임의 정보를 파악하는 법에 대하여 공부해보았다.

이번 포스트에선 데이터프레임에서 새로운 컬럼을 생성하는 방법과 데이터 프레임에 접근하는 법에 대해 공부해보도록 하자.

 

 

 

데이터 프레임 접근

  • 데이터 프레임은 색인과 행과 열의 이름을 통해서 접근할 수 있다.
  • df$colname
    : "데이터프레임$컬럼이름"을 이용하면 데이터프레임에서 원하는 데이터에 접근할 수 있다.
  • df[r, c, drop = TRUE]
    : 데이터프레임 df의 r행, c열의 컬럼에 저장된 데이터를 가지고 올 수 있다.
    r과 c를 벡터로 지정하여 다수의 행과 컬럼을 동시에 가져올 수 있으며, 색인과 행 이름, 열 이름을 지정할 수도 있다. r과 c중 하나만 입력하는 경우, 예를 들어 c 하나만 넣은 경우엔 해당 열에 대한 모든 행 데이터를 가지고 온다.
    • r과 c중 하나만 불러오는 경우, 해당하는 행과 열 데이터만 해당 컬럼의 데이터 타입으로 가지고 오는데, 이러한 형 변환을 원하지 않는 경우엔 drop = FALSE로 지정하면 된다.
  • 인덱싱 방법은 다음과 같다.
    • df$col1
      : 데이터 프레임 df에서 col1 컬럼을 가지고 온다.
    • df[1,]
      : 데이터 프레임 df에서 1번째 행을 가지고 온다.
    • df[c(1,3), 2]
      : 데이터 프레임 df에서 1, 3번째 행을 가지고 오고, 2번째 컬럼을 가지고 온다.
    • df[ , c(2:5)]
      : 데이터 프레임 df에서 2~5번까지 컬럼을 가지고 온다.
    • df[ , -c(2:5)] == df[ , c(-2:-5)]
      : 데이터 프레임 df에서 2~5번 컬럼을 제외하고 가지고 온다.
    • df[ , c("math", "science")]
      : 데이터 프레임 df에서 math와 science 컬럼만 가지고 온다.
  • 위 인덱싱 방법말고도 다른 함수들을 조합해서 가지고 올 수는 있으나, 위 방법만으로도 충분하다.
  • 위 인덱싱 방법들을 응용하여, 내가 가지고 오고 싶은 데이터만 가지고 와보자.
# 데이터 프레임에서 내가 원하는 값만 가지고 와보자.
vt1 = c("민철", "재성", "기훈", "현승", "현택", "윤기" ,"재빈", "현희", "미선", "선화")
vt2 = c(70, 60, 50, 80, 90, 80, 65, 75, 90, 80)
vt3 = c(80, 70, 85, 65, 55, 70, 75, 80, 65, 75)
vt4 = c(75, 80, 90, 75, 85, 75, 80, 85, 80, 85)

exam = data.frame("name" = vt1, "math" = vt2, "english" = vt3, "science" = vt4)
# exam에서 math컬럼만 가지고 오자.
exam$math
##  [1] 70 60 50 80 90 80 65 75 90 80
  • indexing을 하는 경우, 데이터 타입이 바뀔 수 있으므로 주의해야한다.
# exam에서 1번째 행만 가지고 오자.
exam[1,]
##   name math english science
## 1 민철   70      80      75
# exam에서 1, 3행과 2번 컬럼만 가지고 오자.
exam[c(1,3),  2]
## [1] 70 50
# exam에서 2, 3, 4 행과 name, math 컬럼만 가지고 오자.
exam[c(2, 3, 4), c("name", "math")]
##   name math
## 2 재성   60
## 3 기훈   50
## 4 현승   80
# exam에서 3번째 컬럼만 제외하고 가지고 오자.
exam[, -c(3)]
##    name math science
## 1  민철   70      75
## 2  재성   60      80
## 3  기훈   50      90
## 4  현승   80      75
## 5  현택   90      85
## 6  윤기   80      75
## 7  재빈   65      80
## 8  현희   75      85
## 9  미선   90      80
## 10 선화   80      85

 

 

 

 

새로운 컬럼 추가

  • 데이터 프레임에 새로운 컬럼(변수)를 추가하는 방법은 R 자체의 Base 함수를 쓰거나, dplyr과 같은 데이터 핸들링 패키지를 쓰는 방법 등이 있다.
  • 이번 포스트에선 R의 Base 함수를 이용해서 새로운 컬럼을 추가해보자.
  • 데이터 프레임은 indexing 방법이었던, "$변수이름"에 새로운 벡터를 추가하여 컬럼을 추가할 수 있다.
# 컬럼을 추가해보자.
vt1 = c("민철", "재성", "기훈", "현승", "현택", "윤기" ,"재빈", "현희", "미선", "선화")
vt2 = c(70, 60, 50, 80, 90, 80, 65, 75, 90, 80)
vt3 = c(80, 70, 85, 65, 55, 70, 75, 80, 65, 75)
vt4 = c(75, 80, 90, 75, 85, 75, 80, 85, 80, 85)

exam = data.frame("name" = vt1, "math" = vt2, "english" = vt3, "science" = vt4)
# Korean 이라는 과목을 추가해보자
exam$Korean <- c(70, 85, 90, 80, 65, 75, 80, 75, 85, 70)
head(exam)
##   name math english science Korean
## 1 민철   70      80      75     70
## 2 재성   60      70      80     85
## 3 기훈   50      85      90     90
## 4 현승   80      65      75     80
## 5 현택   90      55      85     65
## 6 윤기   80      70      75     75
# 총점을 추가해보자.
exam$total <- exam$math + exam$english + exam$science + exam$Korean
head(exam)
##   name math english science Korean total
## 1 민철   70      80      75     70   295
## 2 재성   60      70      80     85   295
## 3 기훈   50      85      90     90   315
## 4 현승   80      65      75     80   300
## 5 현택   90      55      85     65   295
## 6 윤기   80      70      75     75   300
# 평균점수를 구해보자.
exam$mean <- exam$total/4
head(exam)
##   name math english science Korean total mean
## 1 민철   70      80      75     70   295 73.75
## 2 재성   60      70      80     85   295 73.75
## 3 기훈   50      85      90     90   315 78.75
## 4 현승   80      65      75     80   300 75.00
## 5 현택   90      55      85     65   295 73.75
## 6 윤기   80      70      75     75   300 75.00

 

 

 

지금까지 데이터프레임에 대한 아주 기초적인 학습을 해보았다.

데이터프레임은 지금까지 다룬 내용으로만 끝내기엔, 활용처가 매우 많기 때문에, 다음 포스트인 list형에 대해 학습을 마치고 데이터 핸들링으로 가장 유명한 패키지인 dplyr에 대해 공부를 하면서, 보다 심도 깊게 다뤄보도록 하겠다.

728x90
반응형

'R > Basic' 카테고리의 다른 글

R(기초) 데이터 타입 판별과 타입 변환  (0) 2020.06.22
R(기초) 리스트(List)  (0) 2020.06.22
R(기초) 데이터프레임(Data Frame)(1부)  (0) 2020.06.21
R(기초) 배열(Array)  (0) 2020.06.19
R(기초) 행렬(Matrix)(3부)  (0) 2020.06.19
728x90
반응형

데이터 프레임(Data Frame)

이번 포스트에선 R 데이터 타입의 꽃인 데이터프레임에 대해 학습해보겠다. 데이터프레임은 R에서 가장 중요한 자료형으로, 우리에게 익숙한 액셀의 스프레드시트와 같이 표 형태로 정리한 모습을 가지고 있다.

데이터프레임은 R에서 가장 많이 쓰이는 데이터 타입이며, 대용량의 데이터를 다루기엔 비효율적이라서 빅데이터 분석 시엔 fread를 비롯한 다른 데이터 타입을 사용하지만, 이 역시 기본적으로 데이터 프레임과 비슷한 형태를 가지고 있으며, 다루는 방법 역시 데이터 프레임과 비슷하다.

 

Data Frame의 기본적인 형태

  • 데이터 프레임은 행렬과 같은 모습을 하고 있지만, 행렬과 다르게 다양한 변수, 관측치(Observations), 범주(Category) 등을 표한하기 위해 특화되어 있다.
  • 행렬은 하나의 데이터 타입밖에 사용하지 못하지만, 데이터 프레임은 여러 가지 데이터 타입을 혼용하여 사용할 수 있다.
  • 데이터 프레임의 각 열(Column)별 행(Row)의 길이는 모두 동일하다.
  • 데이터 프레임의 행(Row, Record)은 데이터의 대상이 되는 객체 하나하나 이다.
  • 데이터 프레임의 열(Columns, Variable)은 데이터 대상이 되는 객체의 속성을 나타내는 값이다.
    각각의 Columns은 행렬과 달리 다양한 변수 타입을 가질 수 있다.

 

 

데이터프레임을 만들어보자

  • 데이터 프레임은 벡터, 행렬로 만들 수 있다.
  • 행렬을 그대로 데이터 프레임에 넣거나, 길이가 동일한 벡터들을 컬럼 하나하나에 배정하여 생성하면 된다.
  • data.frame()
    : 데이터 프레임을 생성한다.
  • 주요 Parameter
    : data.frame(stringsAsFactors: 문자열을 자동으로 요인(Factor)형으로 변환해준다.)
    • data.frame에서 중요한 Parameter는 stringsAsFactors말고는 딱히 없다. data.frame에서 다른 Parameter들에 대한 내용을 읽어보고자 한다면, data.frame 코드를 치고 F1을 눌러서 보도록 하자.
    • stringsAsFactors는 간단하지만, 상당히 중요한 Parameter로, 말 그대로 문자열을 요인(Factor)으로 바꿔주는 Parameter이다. 만약 string형인 열을 이용해서 새로운 변수를 만들어내거나, 특정 문자열을 분리해내는 작업을 하지 않는다면, 해당 Parameter를 TRUE로 두어 모두 Factor형으로 바꾸는 것이 유리하다.
    • 그러나, 문자열에 대하여 어떠한 조작을 하는 경우엔, Factor형으론 조작이 매우 힘드므로, 가능하다면 해당 Parameter를 FALSE로 두는 것을 추천한다.

 

1) 벡터를 이용해서 데이터프레임을 만들어보자.

# 벡터로 데이터프레임을 만들어보자
vt1 = c("민철", "재성", "기훈", "현승", "현택")
vt2 = c(70, 60, 50, 80, 90)
vt3 = c(80, 70, 85, 65, 55)

df1 = data.frame(vt1, vt2, vt3)
df1
##    vt1 vt2 vt3
## 1 민철  70  80
## 2 재성  60  70
## 3 기훈  50  85
## 4 현승  80  65
## 5 현택  90  55
  • 데이터 프레임 안에 길이가 동일한 벡터를 넣어주면 된다.
  • 길이가 다른 벡터를 함께 넣는 경우 에러가 뜨며 데이터프레임이 생성되지 않는다.
  • 각 컬럼의 이름은 벡터의 이름으로 정해진다.

 

2) 행렬을 이용해서 데이터프레임을 만들어보자.

# 행렬로 데이터프레임을 만들어보자
vt = c("민철", "재성", "기훈", "현승", "현택", 70, 60, 50, 80, 90, 80, 70, 85, 65, 55)
mat = matrix(vt, ncol = 3, byrow = FALSE)

data.frame(mat)
##    X1  X2  X3
## 1 민철  70  80
## 2 재성  60  70
## 3 기훈  50  85
## 4 현승  80  65
## 5 현택  90  55
  • 데이터 프레임 안에 행렬을 넣어주면 된다.
  • 각 컬럼의 이름은 X1, X2, X3...와 같은 방식으로 생성된다.
  • 행렬은 하나의 변수 타입만 가질 수 있으므로, 행렬을 데이터 프레임으로 바꾸는 경우, 하나의 속성만 가진 형태로 데이터프레임이 만들어진다.
str(data.frame(mat))
'data.frame':	5 obs. of  3 variables:
 $ X1: chr  "민철" "재성" "기훈" "현승" ...
 $ X2: chr  "70" "60" "50" "80" ...
 $ X3: chr  "80" "70" "85" "65" ...
  • 그러니 되도록이면 행렬로 데이터프레임을 만들기보다는 벡터를 이용해서 만들도록 하자.
  • 만약 행렬로 만들어야한다면, 데이터프레임 생성 후, 각 컬럼의 변수 타입을 모두 바꿔주도록 하자.

 

 

 

데이터 프레임 변수의 이름을 바꿔보자.

  • 이번엔 데이터 프레임 컬럼의 이름을 바꿔보자.
  • 데이터 프레임 컬럼 이름 변경은 2가지 방법이 있다.

1) 데이터 프레임 생성 시, 벡터의 이름을 설정해준다.

# 벡터로 데이터프레임을 만들어보자
vt1 = c("민철", "재성", "기훈", "현승", "현택")
vt2 = c(70, 60, 50, 80, 90)
vt3 = c(80, 70, 85, 65, 55)

data.frame("name" = vt1, "math" = vt2, "english" = vt3)
##   name math english
## 1 민철   70      80
## 2 재성   60      70
## 3 기훈   50      85
## 4 현승   80      65
## 5 현택   90      55

 

2) 생성된 데이터 프레임의 이름을 바꿔준다.

  • colnames()
    : data의 column의 이름들을 가지고 온다.
# 변수명을 바꿔보자.
vt1 = c("민철", "재성", "기훈", "현승", "현택")
vt2 = c(70, 60, 50, 80, 90)
vt3 = c(80, 70, 85, 65, 55)

df = data.frame(vt1, vt2, vt3)
colnames(df)
## [1] "vt1" "vt2" "vt3"
  • colnames(df)를 하면, dataframe의  column 이름들을 가지고 온다.
colnames(df) <- c("name", "math", "english")
df
  • colnames(df)에 벡터로 새로운 컬럼의 이름을 부여해보자.
##   name math english
## 1 민철   70      80
## 2 재성   60      70
## 3 기훈   50      85
## 4 현승   80      65
## 5 현택   90      55

 

3) 행의 이름을 바꿔주자.

  • 데이터프레임은 행을 index로 활용할 수 있으며, 행에 변수를 넣을 수도 있다.
  • 단 행의 이름은 절대 중복되서는 안된다.
  • 그러므로, ID를 만들어서 넣거나, 기존의 행 번호를 그대로 사용하도록 하자.
  • rownames()
    : data의 행 이름들을 가지고 온다.
# 행의 이름을 바꿔보자
vt1 = c("민철", "재성", "기훈", "현승", "현택")
vt2 = c(70, 60, 50, 80, 90)
vt3 = c(80, 70, 85, 65, 55)

df = data.frame(vt1, vt2, vt3)
rownames(df)
## [1] "1" "2" "3" "4" "5"
# 데이터프레임의 vt1을 row의 이름으로 사용해보자
rownames(df) <- df[,1]

# 데이터프레임에서 첫번째 컬럼과 행의 이름이 동일하므로, 첫번째 컬럼은 제거해서 가지고 와보자.
df[,-1]
##      vt2 vt3
## 민철  70  80
## 재성  60  70
## 기훈  50  85
## 현승  80  65
## 현택  90  55
  • 이번에 사용한 코드들을 보면, 행렬에서 다뤘던 indexing과 동일한 것을 볼 수 있다.
  • 행렬도 데이터프레임처럼 행의 이름과 열의 이름을 동일한 방법으로 바꿀 수 있다.
  • 데이터프레임의 Indexing에 대해선 다음 포스트에서 더 자세히 다뤄보도록 하겠다.

 

 

 

데이터 프레임의 정보를 살펴보자.

  • 이번엔 데이터프레임의 기본적인 정보를 살펴보는 방법을 보자.
  • str()
    : 데이터프레임의 차원과 각 열에 대한 정보 출력
  • head()
    : 일반적인 데이터프레임은 매우 크므로, 모두 보는 것은 힘들다. head()를 사용하면, 맨 위에서 n개(기본값 6)의 행을 가지고 온다. 데이터프레임을 보고자 한다면, head()를 이용해서 보도록 하자.
  • tail()
    : head()와 반대로 데이터프레임의 맨 아래에서 n개(기본값 6)의 행을 가지고 온다. tail()을 이용하면, 데이터프레임의 맨 아래 부분에 어떠한 특이사항이 있는지를 눈으로 쉽게 확인할 수 있다.
  • summary()
    : 데이터프레임에 있는 변수별 기술통계량을 볼 수 있다.
    변수 타입이 연속형변수인 경우에는 최소값, 최대값, 사분위 수, 평균을 볼 수 있다.
    변수 타입이 문자형과 같은 범주형 변수인 경우에는 변수의 길이, Class, Mode 등을 볼 수 있다.
    (Mode는 R의 기본 배경이 된 언어인 S language와 호환성을 가진 언어로, 간단하게 말하면 과거 버전의 타입 분류 방법이라고 생각하면 된다. R을 사용할 땐, Class가 우선이라고 간략하게 생각하고, Class에만 신경 쓰도록 하자.)
  • dim()
    : 데이터프레임의 차원별 길이를 볼 수 있다.
    데이터 프레임은 행과 열 2개의 차원으로 구성되어 있으며, dim() 함수를 이용하면 행의 수, 열의 수를 볼 수 있다.
  • View()
    : 데이터프레임을 데이터 뷰어창에서 볼 수 있다.
    데이터프레임 뿐만 아니라 행렬, 벡터 등도 볼 수 있다.
# 데이터 프레임의 구조를 살펴보자.
vt1 = c("민철", "재성", "기훈", "현승", "현택", "윤기" ,"재빈", "현희", "미선", "선화")
vt2 = c(70, 60, 50, 80, 90, 80, 65, 75, 90, 80)
vt3 = c(80, 70, 85, 65, 55, 70, 75, 80, 65, 75)

df = data.frame("name" = vt1, "math" = vt2, "english" = vt3)
df
##    name math english
## 1  민철   70      80
## 2  재성   60      70
## 3  기훈   50      85
## 4  현승   80      65
## 5  현택   90      55
## 6  윤기   80      70
## 7  재빈   65      75
## 8  현희   75      80
## 9  미선   90      65
## 10 선화   80      75
# 데이터 프레임의 차원과 각 열에 대한 정보를 알아보자.
str(df)
## 'data.frame':    10 obs. of  3 variables:
##  $ name   : chr  "민철" "재성" "기훈" "현승" ...
##  $ math   : num  70 60 50 80 90 80 65 75 90 80
##  $ english: num  80 70 85 65 55 70 75 80 65 75
# 데이터 프레임의 위부터 n행까지 추출한다(기본값은 6).
head(df, n = 5)
##   name math english
## 1 민철   70      80
## 2 재성   60      70
## 3 기훈   50      85
## 4 현승   80      65
## 5 현택   90      55
# 데이터 프레임의 아래부터 n행까지 추출한다(기본값은 6).
tail(df, n = 5)
##    name math english
## 6  윤기   80      70
## 7  재빈   65      75
## 8  현희   75      80
## 9  미선   90      65
## 10 선화   80      75
# 변수별 요약통계량 출력
summary(df)
##      name                math          english     
##  Length:10          Min.   :50.00   Min.   :55.00  
##  Class :character   1st Qu.:66.25   1st Qu.:66.25  
##  Mode  :character   Median :77.50   Median :72.50  
##                     Mean   :74.00   Mean   :72.00  
##                     3rd Qu.:80.00   3rd Qu.:78.75  
##                     Max.   :90.00   Max.   :85.00
# 데이터 프레임의 차원별 길이 출력
dim(df)
## [1] 10  3
# 데이터 뷰어로 데이터 프레임을 보자.
View(df)

  • View() 함수를 이용하는 경우, 데이터 프레임을 데이터 뷰어라는 새로운 창에서 크게 볼 수 있다.
  • R에서 매우 큰 데이터 프레임을 head()나 tail()가 아닌 그 자체로 불러오는 경우, R이 뻗어버릴 수 도 있지만(너무 큰 데이터를 표현하면, 부하가 매우 크므로, 가능한 dataframe 이름만 쳐서 가지고 오는 행동은 하지 말자) View를 사용해서 데이터 뷰어에서 보면 R이 뻗지는 않는다.
    (물론, 데이터의 크기가 너무 크므로, 보는 것이 굉장히 불편하긴 하다.)

 

 

지금까지 데이터프레임을 만들고 데이터프레임의 기본적인 정보를 보는 법에 대해 학습해보았다.

다음 포스트에선 데이터프레임에 새로운 변수를 추가해보거나, Indexing 하는 방법 등을 공부해보자.

728x90
반응형

'R > Basic' 카테고리의 다른 글

R(기초) 리스트(List)  (0) 2020.06.22
R(기초) 데이터프레임(DataFrame)(2부)  (0) 2020.06.22
R(기초) 배열(Array)  (0) 2020.06.19
R(기초) 행렬(Matrix)(3부)  (0) 2020.06.19
R(기초) 행렬(Matrix)(2부)  (0) 2020.06.19

+ Recent posts