반응형
반응형

1. 연산자 오버로딩

  1. 연산자 오버로딩시 const를 사용하라!
  2. 연산자 오버로딩 방법 두 가지

1)멤버 함수 오버로딩

  • 구현 : 멤버 함수로 연산자를 오버로딩
Point operator+(const Point& ref);
// 사용시 해석
pos.operator+(pos2);

2)전역 함수 오버로딩

  • 구현 : 전역 함수로 구현하고 클래스 내에서 friend 정의
  • 멤버 변수 접근 안되므로 getter 또는 friend 필요!
// 클래스 내부에서 정의
friend Point operator+(Point&, Point&);
// 클래스 밖에서 전역 함수 구현
Point operator+(Point& pos1, Point& pos2){}
// 사용시 해석
operator+(pos1, pos2);
  1. 무조건 전역 함수 오버로딩을 사용하는 경우

    • 이항 연산의 왼쪽항이 오버로딩 객체가 아닐 때 사용

    • Point 객체에 상수 3을 곱할 경우

Point operator*(int, Point&);

//사용
Point pos2 = pos * 3;
  1. 객체를 cout 가능하게 하기
    • ostream을 전역 함수 오버로딩 사용
ostream& operator<<(ostream& os, Point& pos){
    os <<'('<< x << ',' << y << ')' << endl;
    return os;
}
  1. 연산자 오버로딩 시 주의 사항
    • Animal 클래스(부모) 에서 연산자 오버로딩
    • Cat 클래스(자식)에서 연산자 오버로딩 안함
    • 위의 상태에서 연산자 오버로딩 사용시 문제 발생 가능
if (Cat1 == Cat2)
// 서로 다른 객체 이지만 부모가 동일하여 True발생 가능함
// Cat에도 연산자 오버로딩을 작성해야 함!

2. 단항 연산자 오버로딩(++)

  1. 전위 증가
const Point& operator++(){
    m_nX++;
    m_nY++;
    return *this;
}
++pos1;
  1. 후위 증가
const Point operator++(int){
    const Point refPos(m_nX, m_nY);
    m_nX += 1;
    m_nY += 2;
    return refPos;
}
pos1++;

3. 대입 연산자 오버로딩

  1. 이미 생성 및 초기화 되었으면 = 기호 사용시 대입 연산자 호출됨
  2. 대입 연산자 미구현 시 Defualt 대입 연산자 생성 및 호출
    • 얕은 복사 진행
  3. 상속 시 부모 클래스의 대입연산자를 명시적으로 호출 필요
First::operator=(ref);

4. new, delete 오버로딩

  1. new 연산자 오버로딩
    • new 연산자의 수행 범위 3가지
      • 메모리 할당
      • 생성자 호출
      • 할당 자료형 변환
    • 위 중 메모리 할당 역할만 오버로딩 가능
  2. new, delete 오버로딩 함수는 static 함수
    • 일반 함수로 선언해도 static 함수로 간주
    • 객체 생성 전 호출되어야되는 함수이기 때문
  3. 구현 방법
//new
void* operator new(size_t size) {...}
void* operator new[](size_t size()) {
    void* adr = new char[size];
    return adr;
}

//delete
void operator delete(void* adr)
void operator delete[](void* adr){
    delete[] adr;
}

5. 포인터 연산자 오버로딩

  1. 포인터 연산자 오버로딩
Number& operator*(){
    return *this;
  1. 지시 연산자 오버로딩
Number* operator->(){
    return this;
}

6. 함수 호출 연산자 오버로딩

struct FuncObj{
   int Add()(int a, int b) const{
      return a + b;
   }
}

int main(){
   FuncObj add;
   std::cout<<add(10,20);
}

7. 배열 인덱스 연산자 오버로딩

  1. 값 조회용 오버로딩
int operator[](int idx) const{
   return arr[idx];
}
  1. 값 입력용 오버로딩
int& operator[](int idx) {
   return add[idx];
}

8. 일반 변수 오버로딩

operator int(){
   return x;
}

int main(){
   Point pos(3,2);
   int a = pos; // a는 3을 가짐
}
반응형

'C++ > C++' 카테고리의 다른 글

[C++]스마트 포인터  (0) 2021.03.09
[C++]LR value 및 최적화  (0) 2021.03.09
[C++]빌드 프로세스  (0) 2021.03.09
[C++]메모리 구조  (0) 2021.03.09
[C++]기초 내용 정리  (0) 2021.03.09
반응형

1. 헤더 가드

  1. 필요성
    • 헤더가 중복으로 로딩되면 오류가 발생할 수 있음
    • 이미 헤더가 로딩되었을 경우는 로딩하지 않도록 정의
  2. 사용방법
    • C style
#ifndef TEST
    #def TEST
    //헤더 내용
#endif
  • C++ style
#progma once
    //헤더 내용

2.구조체와 클래스 유일한 차이

  1. 별도의 접근제어 지시자를 입력하지 않으면
    • 구조체 : public이 default
    • 클래스 : private이 default

3. inline 함수

  1. 매크로 함수 특징(#define)
    • 일반 함수보다 실행속도가 빠르다.
    • 복잡한 함수를 정의하기 어렵다.
    • 전처리기에 의해 처리된다.
    • 자료형에 의존적이지 않은 함수 가능
    • 사용 방법
#define SQUARE(x) ((x)*(X))
  1. inline 함수 특징
    • 컴파일러에 의해 처리된다.
    • 템플릿을 이용해 자료형에 의존적이지 않은 함수 가능
    • 사용 방법
inline int SQUARE(int x){
    return x*x;
}

4. 객체간의 대화방법(Message Passing)

  1. 한 객체가 다른 각체에게 메시지 전달 방법

    ex) seller 아저씨 사과 2000원 어치 주세요.

void Buyer::BuyApples(Seller &sel, int mon)

5. const

  1. const 함수
    • 함수 내에서 멤버 변수를 변경 안함
    • 함수 내에서 const가 아닌 함수 호출 제한
int GetY() const;
  1. const 객체
    • 객체는 const 멤버 함수만 호출 가능
const Simple sim(20)
  1. mutable 키워드

    • const 함수에서 예외적으로 값 변경 허용
mutable int num;

6. 멤버 이니셜라이저

Point pos;
string name;
car::car(int x, int y, string s)
    : pos(x,y), name(s) {}
  1. 객체 pos에 x,y를 전달받는 생성자 호출
  2. 일반적인 변수(name)도 이니셜라이저로 초기화 가능
  3. 선언과 동시에 초기화 해주는 형태로 바이너리 코드가 생성됨
  4. const 변수도 초기화 가능함
  5. 참조자도 초기화 가능함
Position& pos
Car(Position &pos1) : pos(pos1) {}

7. 생성자

  1. 생성자를 생략해도 무조건 생성자 호출됨
    • Default 생성자가 자동 생성 후 호출됨
  2. malloc으로 객체 생성 시 생성자 호출 안됨
  3. new로 객체 생성 시 생성자 호출됨
  4. 생성자가 있으면 Default 생성자 자동 생성 안됨

8. Self reference

  1. this 포인터를 이용해 자기자신을 반환 가능
SelfRef& Add(int a){
    this->num+=a;
    return *this;
}
  • ref.Add(1).Add(1)과 같이 사용 가능

9. 복사 생성자

  1. 복사 생성자 미정의시 Default 복사 생성자 생성
Simple(const Simple& copy)
  1. 복사생성자 인자에는 반드시 &가 있어야함
  2. explicit 키워드
    • 아래와 같은 묵시적 변환이 안 일어나게 하는 것
    • 묵시적 변환이 많으면 코드 예측 어려움
Simple sim2 = sim1
// Simple sim2(sim1)
// => 위와 같은 형태로 묵시적 변환 일어남
// => explicit 키워드 붙혀줌
explicit Simple(const Simple &copy)
  1. 얕은 복사
    • 포인터 변수 복사 시 원래 변수의 주소만 복사함
    • 원래 변수가 변경되면 같이 변경됨
    • Default 복사 생성자는 얕은 복사 수행
  2. 깊은 복사
    • 포인터 변수 복사 시 메모리를 재할당 받도록 복사 생성자를 별도로 정의
  3. 복사 생성자의 호출 시점(3가지)

1)기존 객체를 이용해 새로운 객체를 초기화

Simple sim = sim2

2)call by value 방식으로 객체를 인자로 전달

void func(Simple sim)

3)참조형이 아닌 객체 반환

  • func에서 return 될 때 임시 객체 생성
  • 받는 ref가 없으면 임시 객체 즉시 소멸
  • 받는 ref가 있으면 받는 ref가 소멸될 때 소멸
  • ref는 임시객체에 이름만 부여(재복사 안함)
Simple func(Simple ref) {
    return ret;
}

Simple ref = func(obj);

10. friend

  1. A클래스에서 B클래스를 friend 선언 시
    • B클래스에서 A클래스의 private 멤버 접근 가능
    • friend 선언 시에 클래스 원형 선언도 포함함
class B; // friend 선언시 원형을 포함하므로 이구문 필요 없음

// A클래스 에서 아래 입력...
friend class B;
  1. A클래스에서 friend 함수 선언 시
    • 함수에서 private 멤버 접근 가능
// A클래스에서 아래 입력...
friend void showPtn(const Point& pnt)

void showPtn(const Point& pnt){
    // A클래스 멤버 접근 가능
}
  1. friend는 가급적 사용을 지양
    • 꼭 필요한 경우에만 사용

11. static

  1. static 멤버 변수(클래스 변수)
    • 클래스 당 하나씩만 생성됨
    • public으로 선언시 클래스명::변수명 사용 가능
    • 클래스 밖에서 초기화 필요
// Simple 클래스
static int cnt;

// 클래스 외부에서 초기화 필요
int Simple::cnt = 0;
  1. static 멤버 함수

    • 함수 내부에서 static 멤버 변수와 static 멤버 함수만 호출 가능
    • 일반 멤버 변수 접근 불가
    • 클래스명::함수명() 형태로 사용 가능
  2. const static 멤버

    • 선언과 동시에 초기화 가능
const static int KOR = 100;

12. 상속

  1. 자식 클래스 생성자에서 부모 클래스 생성자를 명시하지 않으면 부모 클래스의 void 생성자 호출
  2. protected 상속
    • public 멤버는 protected로 변경하여 상속
  3. public 상속
    • 별도 변경 없음
  4. private 상속
    • 모든 멤버를 private로 변경하여 상속
  5. 상속의 조건
    • is a 관계(노트북 is a 컴퓨터)가 성립해야함
  6. has a 관계도 상속 가능하지만 일반적으로 다른 기술들 사용

13. 상속과 다형성

  1. 부모 클래스 포인터 변수는 모든 자식 객체를 가리킬 수 있다
base* ptr = new derived();
  1. 그러나 함수 호출은 포인터형에 해당하는 멤버만 호출 가능
ptr->derivedFunc() // (X)
  1. virtual 함수 사용시 포인터 변수가 실제 가리키는 객체를 참조하여 호출 대상 결정
virtual void myFunc();

Person* ptr = new Student();
ptr->myFunc(); // => Student의 myFunc 호출됨
  1. 순수 가상 함수
    • 함수의 몸체를 정의하지 않음을 컴파일러에 알림
    • 순수 가상함수를 지닌 클래스는 객체 생성 불가
virtual int getPay() = 0;
  1. 가상 소멸자
// 1. 일반 소멸자 정의
~Person();

Person* ptr = new Student();
delete ptr; // => Person의 소멸자만 호출됨

// 2. 가상 소멸자 정의
virtual ~Person();

Person* ptr = new Student();
delete ptr; // => Student 소멸자도 호출됨

14. 가상의 원리와 다중 상속(effective 7 참고)

  1. virtual 함수 생성하면 컴파일 시 포인터 주소 추가

    • 64비트 기준 객체의 크기가 8바이트 증가
    • 포인터는 virtual 테이블을 가리킴
  2. virtual 테이블이 각 함수를 가리킴

    • Animal VT는 Animal의 speak()
    • cat VT는 Cat의 speak()
  3. 함수 호출 시 가상 함수 테이블에서 찾아서 호출

  4. 가상 상속

    • 다중 상속에서 두 개의 부모가 같은 Base를 가지고 있을 때 Base를 한번만 상속하는 방법
class MidOne : virtual public Base{...}
class MidTwo : virtual public Base{...}
class Last : public MidOne, public MidTwo{...}
  1. 일반 상속 시(Lion이 Animal을)
    • VT 포인터 하나 가짐
    • 포인터 시작지점은 Animal
    • Animal이 끝나면 Lion 정보가 메모리에 존재
  2. virtual 상속시
    • lion 클래스 포인터 시작이 lion
    • animal, lion의 VT 포인터 모두 가짐
    • Animal 포인터로 lion 가리키면 Lion VT의 offset 정보를 가지고 있음(16바이트 전에 Lion의 시작점이 있다.)
    • thunk 함수를 통해 Lion::speak 함수 호출 가능
    • thunk 함수는 offset을 계산한 Lion::speak 함수를 가리킴
    • Lion 포인터로 Lion 가리키면 그냥 호출 가능

15. 템플릿

  1. 함수 템플릿 사용 방법
// 1. 생성
template<typename T>
T Add(T num1, T num2) {}

// 2. 사용
Add<int>(3,4); // int형
Add<int>(3,5,4.5); // double형
  1. typename 대신 class 사용 가능
template<class T>
  1. 컴파일 때 입력된 자료형에 맞게 함수가 생성됨

    • 최초 1회 생성, 이후는 생성된 함수 사용
    • 컴파일 속도가 약간 느려짐
  2. 용어 정리

    • 함수 템플릿 : 함수를 만드는 템플릿 정의
    • 템플릿 함수 : 템플릿에 의해 생성된 함수
  3. 일반 함수가 정의되어 있으면, 템플릿 함수보다 우선 호출됨

  4. 템플릿 타입 여러 개 적용 가능

template<class T1, class T2>
void ShowData(T1 num1, T2 num2)

// 사용
ShowData<int, double>(65, 3.6) // int, double형
}
  1. 함수 템플릿의 특수화
    • 특정 인자로 들어오면 명시적으로 특정 함수를 사용하게 정의 하는 것
    • ex) Max함수에서 문자가 들어오면 길이 비교
template<>
char* Max<char*>(char* a, char* b){
    return strlen(a) > strlen(b) ? a : b;
}
  1. 클래스 템플릿
//1. 선언
template<typename T>
class Point {
    T xpos, ypos;
public:
    Point(T x, T y)
    : xpos(x), ypos(y) {}
};

// 사용
Point<int> pos(1,2); //int형 Point 객체
Point<double> pos(1.1, 3.1) // double형
  1. 선언부와 구현부 파일 분리시 주의 사항

    • 템플릿 사용 함수 위에 template 입력 필수!
    • 사용하는 파일에서 템플릿 cpp 파일도 include 필요
    • 일반적으로 헤더파일안에 구현부도 포함
  2. 클래스 템플릿 특수화

    • 특수 자료형을 기반으로 생성된 객체에 대해 구분되는 다른 행동 양식 적용!
template<>
class SoSimple<int>{
    public:
    int Simplefunc(int num){...}
}
  1. 템플릿 인자 및 기본값 설정
template<typename T = int, len = 7>
class SimpleArray{
    T arr[len];
}

16. 예외 처리

  1. try
    • 예외를 발견 한다.
  2. catch
    • try블록에서 발생한 예외를 처리하는 로직
  3. throw
    • 예외가 발생 했음을 알림
  4. 예제
try {
    if(num2 == 0)
        throw num2;
} catch(int expn) {
    cout << expn <<"은 못옴!";
}
  1. 함수에서 예외 처리가 되지 않았을 때
    • 함수를 콜한 영역으로 예외처리에 대한 책임과 데이터 전달됨
    • 함수에 대한 예외 발생 시 함수 호출한 곳에서 예외 처리 가능
// 예외를 던지는 함수
void Divide(int num1, int num2){
    if(num2 == 0)
        trhow num2;
}

// 함수를 콜하는 부분
// Divide 함수 수행 하다 예외 발생시
// 아래 catch 부분에서 예외 처리 가능
try{
    Divide(num1, num2);
} catch(int expn){ ... }
  1. 함수 선언시 throw 키워드 추가
    • 예외 발생이 있다면 throw 키워드를 꼭 붙여야함!
int Func(int num) throw(int, char)
// int와 char 형식의 예외 발생이 가능하다!
// 이 함수 사용시 try catch문이 필요하다고 알림
  1. 클래스 형태로 예외 정의 가능
    • 예외 클래스를 정의
    • 예외 클래스는 exception 클래스를 상속!
void deposit(money) {
    if ( money < 0 ) {
        //expn 예외 객체 생성 및 throw 발생
        DepositException expn(money) ;
        throw expn;
    }
}
try {
    deposit(-200) ;
} catch ( DepositException &expn) {
    expn.showError();
}

17. C++ 형변환 연산자

  1. dynamic_cast(expr)
    • 상속 관계에서 안전한 형 변환 가능
    • T에 객체는 포인터 또는 참조형 가능
    • 실행시간에 형변환 되므로 속도 느림
  2. static_cast(expr)
    • C스타일의 형변환 연산자 대신 사용
    • 컴파일 시간에 형변환 되므로 속도 빠름
    • 설계 잘되어 있다면 dynamic 대신 static 사용
  3. const_cast(expr)
    • 참조자의 const 성향을 제거하는 형변환
    • 주로 인자 전달시 불일치 제거를 위해 사용
  4. reinterpret_cast(expr)
    • 전혀 상관이 없는 형 변환에 사용

18. 함수 포인터

  1. 정적 함수 호출
    • 일반 함수나 static 멤버 함수를 가리키는 포인터
    • 선언
// 선언
void (*pFunc)(int);
// 반환값이 void이고 인자가 int형 하나인 함수를 가리킬 수 있는 함수 포인터
  1. 멤버 함수 호출
    • 선언
void(Point::*pFunc)();
// 반환값이 void이고 인자가 없는 Point 멤버 함수를 가리킬 수 있는 함수 포인터 선언

//사용
Point pt;
(pt.*pFunc)(); // 객체로 사용
Point *p;
(p->*pFunc)(); // 주소로 사용

19. 함수 객체

  1. 장점
    • 객체 이므로 멤버 변수, 멤버 함수를 가질 수 있음
    • 속도가 일반 함수보다 빠름
    • 인라인화 될 수 있음(함수 포인터는 안됨)
    • 컴파일러가 쉽게 최적화 가능
//선언
struct Adder{
   int operator()(int a, int b){
      return a_b;
   }
};


int main(){
// 사용1
   Adder add;
   add(3,2);

// 사용2 : 인자로 전달
   for_each(arr, arr+5, Adder());
}

20. C++ 팁

  1. 클래스의 크기는 가장 큰 멤버 변수의 배수로 끝남
    • double이 있으면 8의 배수로 끝남
  2. 각 변수는 자기 크기의 배수에서 시작함
    • double는 8의 배수에에서 시작함
    • 만약 int, double순으로 멤버 변수 선언시
    • 4(int), 4(padding), 8(double)로 저장됨
  3. 클래스에 로우 포인터가 멤버 변수로 있으면
    • 파괴자, 복사/이동 생성자, 복사/이동 대입 구현 필요
  4. 클래스에 로우 포인터 없다면
    • defualt 복사/이동 생성자/대입연산자 사용
  5. 생성자가 private에 있는 것과 =delete는 동일
  6. 생성자 인자가 1개이면 앞에 explicit 명시
    • 원하지 않는 형변환을 방지
    • 링크 참고
Point pt;
pt = 10 //(x)
pt = Point(10) // (O)
  1. iotream 상속 구조
    • 여기서 basic iostream이 자주쓰는 iostream
    • print 함수 구현시 ostream&을 인자로 사용하면, 상속 구조에 따라 ostreamstream, ofstream도 사용 가능
//사용 1. cout
    print(cout) => 화면에 결과 출력
//사용 2. fstream
    ofstream ofs{"test.txt"};
    print(ofs) => 파일에 결과 쓰기
//사용 3. stringstream
    stringstream ss;
    print(ss) => string에 쓰기
반응형

'C++ > C++' 카테고리의 다른 글

[C++]스마트 포인터  (0) 2021.03.09
[C++]LR value 및 최적화  (0) 2021.03.09
[C++]빌드 프로세스  (0) 2021.03.09
[C++]메모리 구조  (0) 2021.03.09
[C++]연산자 오버로딩  (0) 2021.03.09
반응형

안녕하세요. PSYda 입니다.

본 포스팅은 최근 Nomad Coders 의 "React JS로 웹서비스 만들기" 강의를 들으며 제가 이해한 내용을 정리한 내용입니다.

해당 강의는 https://academy.nomadcoders.co/courses/에서 확인 하실 수 있습니다.

 

Academy

[초급] CSSNext, Flexbox, CSS Grid % Complete

academy.nomadcoders.co

 

이번 포스팅에서는 React에 대해 간단히 알아볼 예정입니다.

 

1. 설치 요구사항

1) node.jshttps://nodejs.org/ko/download/ 사이트에서 설치

    - cmd창에서 node -v 를 입력하여 설치된 version 확인

2) npm : node.js 설치하면 자동으로 설치됨

    - cmd창에서 npm –v 입력하여 설치된 version 확인

3) npx : npm을 통해서 설치

    - cmd창에서 npm install npx –g 명령어 입력

4) git : https://git-scm.com/download/win 에서 OS에 맞게 설치

    - cmd창에서 git --version 명령어 입력하여 잘 설치 되었는지 확인

5) vscode https://code.visualstudio.com/ 에서 설치

   - 다른 IDE를 써도 되지만 vscode가 제일 핫함

 

2. 이론 요구사항

React JS를 배우기 전에 알아야 할 내용들은 무엇일까?

1) HTML : div, span, flexbox, display block, backgound color

2) CSS

3) Javascript : function, variable, class, const, let, array, object 등

4) node.js : package.json

 

3. Why React?

1) 많은 회사들이 React를 사용하고 있음

   - Facebook이 만들었고, 모든 facebook은 React로 구현되었음

   - Airbnb, npm, neflix 등 많은 회사들이 React로 구현하였음

 

2) 프론트엔드에서 아주 핫한 Library

   - npm에서 react Library 정보를 살펴 보면 1주에 5백만 건 이상 다운로드

     (https://www.npmjs.com/package/react)

   - 2018년 프론트엔드 개발 생태계 설문조사에서 React가 압도적으로 1등

     (https://2018.stateofjs.com/front-end-frameworks/overview/?no-cache=1)

3) 커뮤니티가 잘 활성화 되어 있음

 

4) Javascript 기반의 언어

   - React가 사라지더라도 Javascript 지식은 남길 수 있음

   - Angular의 경우 문법이 완전 새롭기 때문에, 사라지면 남는게 없음

 

5) 그 외의 React를 쓰는 이유(아래 사이트 참고)

   - https://2018.stateofjs.com/front-end-frameworks/react/

 

다음 시간에는 실제로 React App 을 만드는 과정을 알아볼 예정입니다.

다음 포스팅 바로 가기 :

https://programmerpsy.tistory.com/26

불러오는 중입니다...

 

감사합니다.

반응형
반응형

안녕하세요. PSYda입니다.

이번 포스팅에서는 DataFrame의 집계(그루핑) 함수에 대해 알아보겠습니다.

집계함수란 데이터를 몇몇의 집단으로 나누어 집단간 평균, 합계 등의 연산을 수행하는 함수를 얘기합니다.
예를 들어 고등학교 학생 전체 성적 데이터가 있을 경우 반별영어성적에 대한 평균을 내거나, 과목별로 학생들의 성적에 대한 평균을 내는 것과 같습니다.
예와 같이 집계함수를 적용하기 위해서는 3가지 값이 필요하며, 그 값은 그룹할 기준(반별 또는 과목별), 연산을 수행할 값(영어성적), 연산 함수(평균) 입니다.

이번 포스팅에서 소개할 내용을 요약하면 아래와 같습니다.

  • groupby 함수을 사용한 DataFrame 집계
  • pivot_table 함수를 사용한 DataFrame 집계

실습에 사용한 데이터는 fifa19에 등장하는 축구선수들의 능력치 데이터입니다.
데이터는 아래에서 다운로드 받을 수 있습니다.

Ch10_1_fifaStats2.csv
다운로드

9. DataFrame의 집계함수

DataFrame을 집계할 수 있는 두 개의 함수

  • groupby
  • pivot_table

9.1 groupby 함수

groupby 함수를 사용한 집계 연산은 두 단계로 이루어짐

  • DataFrame을 그룹별로 나누는 단계
  • 나누어진 그룹에서 집계 함수(sum, mean, max 등)를 수행하는 단계

Library import

import pandas as pd
from pandas import Series , DataFrame
import numpy as np
player = pd.read_csv('data/Ch10_1_fifaStats2.csv')
player.head()

Name Age Nationality Club Preferred Foot Crossing Dribbling LongPassing ShotPower
0 L. Messi 31 Argentina FC Barcelona Left 84.0 97.0 87.0 85.0
1 Cristiano Ronaldo 33 Portugal Juventus Right 84.0 88.0 77.0 95.0
2 Neymar Jr 26 Brazil Paris Saint-Germain Right 79.0 96.0 78.0 80.0
3 De Gea 27 Spain Manchester United Right 17.0 18.0 51.0 31.0
4 K. De Bruyne 27 Belgium Manchester City Right 93.0 86.0 91.0 91.0

9.1.1 그룹핑 한줄로 수행하기

팀별선수의 능력치에 대한 평균값 확인(최상위 5개 팀 조회)

spByTeam = player.groupby('Club').mean()
spByTeam.sort_values(by = 'LongPassing', ascending = False).head()

Age Crossing Dribbling LongPassing ShotPower
Club
Chelsea 25.212121 59.484848 65.666667 65.787879 64.060606
FC Barcelona 23.848485 59.818182 66.121212 65.727273 64.303030
Manchester United 24.757576 62.242424 66.878788 65.727273 66.151515
Manchester City 23.909091 59.696970 66.151515 65.727273 65.606061
Paris Saint-Germain 24.566667 63.133333 68.833333 65.500000 64.500000

특정 하나의 컬럼만 조회하기(Series로 결과 출력됨)
팀별Shotpower평균을 계산하여 평균값이 제일 높은 5개 팀 조회

spByTeam2 = player.groupby('Club')['ShotPower'].mean()
spByTeam2.sort_values(ascending = False).head()
Club
Juventus          68.000000
Ajax              67.400000
Olympiacos CFP    67.000000
SL Benfica        66.714286
Lazio             66.687500
Name: ShotPower, dtype: float64

특정 두 개 이상의 컬럼 조회(DataFrame으로 결과 출력됨)
팀별롱패스와 드리블 능력치 평균값 계산하여 최상위 5개 팀 조회

spByTeam3 = player.groupby('Club')[['LongPassing', 'Dribbling']].mean()
spByTeam3.sort_values(by = 'LongPassing', ascending = False).head()

LongPassing Dribbling
Club
Chelsea 65.787879 65.666667
FC Barcelona 65.727273 66.121212
Manchester United 65.727273 66.878788
Manchester City 65.727273 66.151515
Paris Saint-Germain 65.500000 68.833333

두 개 이상의 변수로 그룹핑(Multi Index로 결과 조회됨)
팀 + 나라로 그룹핑하여 롱패스와 드리블 능력치 평균값 최상위 5개 팀+나라 조회

spByTeam4 = player.groupby(['Nationality','Club'])[['LongPassing', 'Dribbling']].mean()
spByTeam4.sort_values(by= 'LongPassing', ascending = False).head()

LongPassing Dribbling
Nationality Club
Germany Real Madrid 93.0 81.0
Croatia FC Barcelona 90.0 84.0
Denmark Tottenham Hotspur 88.0 84.0
Croatia Real Madrid 88.0 90.0
Argentina FC Barcelona 87.0 97.0

9.1.2 groupby 원리 파헤치기

9.1.2.1 groupby 함수를 이용하면 Groupby 객체가 생성됨

playerGroup = player.groupby('Club')
playerGroup
<pandas.core.groupby.generic.DataFrameGroupBy object at 0x000002211EE1F940>

groupby 객체에서 groups 함수를 이용해 그룹별로 나누어진 값을 dict형태(key와 values)로 확인 가능

playerGroup.groups
{' SSV Jahn Regensburg': Int64Index([ 4587,  4840,  5260,  5335,  6184,  6783,  6917,  6954,  7184,
              7195,  7633,  7657,  7867,  8337,  8933,  9024,  9212, 10285,
              10312, 10686, 11059, 11244, 11861, 12363, 12671, 14161, 14319,
              16105, 17786],
            dtype='int64'),
  '1. FC Heidenheim 1846': Int64Index([ 2053,  4348,  4812,  5093,  5722,  6135,  6208,  6294,  6333,
              6545,  6678,  7595,  7723,  8543,  8567,  9040,  9380,  9535,
              9890, 12004, 12350, 12356, 12654, 14737, 15318, 15842, 16503,
              17538],
            dtype='int64'),
  '1. FC Kaiserslautern': Int64Index([ 5084,  5445,  6372,  7728,  8550,  9335,  9487,  9554,  9563,
              9812,  9886, 10211, 10469, 10554, 11029, 11091, 12485, 14037,
              14758, 15230, 15285, 15392, 15951, 16788, 17268, 17524],
            dtype='int64'),
  ......

9.1.2.2 groupby 객체를 이용해 집계함수 사용

  • 하나의 집계 함수 적용 : groupby객체.집계함수명()
  • 여러개의 집계 함수 적용 : groupby객체.agg([집계함수명1,집계함수명2]) 사용(Multi Column 형태로 출력됨)

groupby 객체의 mean 함수 호출

playerGroup.mean().head()

Age Crossing Dribbling LongPassing ShotPower
Club
SSV Jahn Regensburg 25.655172 47.172414 52.655172 45.689655 54.137931
1. FC Heidenheim 1846 24.000000 49.464286 54.214286 48.964286 57.071429
1. FC Kaiserslautern 23.846154 48.076923 49.769231 48.653846 56.692308
1. FC Köln 24.321429 52.357143 57.964286 54.714286 58.178571
1. FC Magdeburg 24.692308 46.500000 51.346154 47.153846 52.269231
playerGroup.agg(['mean', 'sum']).head()

Age Crossing Dribbling LongPassing ShotPower
mean sum mean sum mean sum mean sum mean sum
Club
SSV Jahn Regensburg 25.655172 744 47.172414 1368.0 52.655172 1527.0 45.689655 1325.0 54.137931 1570.0
1. FC Heidenheim 1846 24.000000 672 49.464286 1385.0 54.214286 1518.0 48.964286 1371.0 57.071429 1598.0
1. FC Kaiserslautern 23.846154 620 48.076923 1250.0 49.769231 1294.0 48.653846 1265.0 56.692308 1474.0
1. FC Köln 24.321429 681 52.357143 1466.0 57.964286 1623.0 54.714286 1532.0 58.178571 1629.0
1. FC Magdeburg 24.692308 642 46.500000 1209.0 51.346154 1335.0 47.153846 1226.0 52.269231 1359.0

9.2 pivot_table 함수

<span class = "hlblock>player.pivot_table(index, columns, values, aggfunc)

  • index : 출력에 사용할 index(그루핑 대상 컬럼)
  • columns : 출력에 사용할 columns
  • values : 집계함수를 적용할 컬럼명
  • aggfunc : 사용할 집계 함수, 여러 개 사용할 경우 [] 안에 집계함수 리스트 작성

EX) 팀별드리블 능력치평균을 구해 상위 5개팀 출력

player.pivot_table(index = 'Club', values = 'Dribbling', aggfunc = 'mean').sort_values(by = 'Dribbling', ascending = False).head()

Dribbling
Club
Juventus 69.520000
Paris Saint-Germain 68.833333
Napoli 68.640000
Liverpool 68.212121
Borussia Dortmund 68.151515

EX2) 나라 + 팀 별로 롱패스와 슟파워평균과 최대값을 계산

player.pivot_table(index = ('Nationality','Club'), values = ('LongPassing','ShotPower'), aggfunc = ('mean','max')).head()

LongPassing ShotPower
max mean max mean
Nationality Club
Afghanistan Notts County 60.0 60.0 60.0 60.0
Philadelphia Union 59.0 59.0 61.0 61.0
SV Meppen 42.0 42.0 39.0 39.0
Walsall 55.0 55.0 55.0 55.0
Albania AC Ajaccio 61.0 61.0 69.0 69.0

위의 Jupyter notebook 내용은 여기 Github에서도 확인 할 수 있습니다.

감사합니다.

반응형
반응형

안녕하세요. PSYda입니다.

Series와 DataFrame을 다루다 보면 각각의 열/행 데이터에 함수를 일괄적으로 적용해야 할 때가 있습니다.

이번 포스팅에서는 Series와 DataFrame의 요소에 함수를 적용하는 방법에 대해 알아보겠습니다.

소개할 내용은 아래와 같습니다.

  • Series 각각 요소에 함수 일괄 적용(map함수)
  • DataFrame의 행, 열 별 함수 일괄 적용(apply함수)
  • DataFrame의 요소에 함수 일괄 적용(applymap함수)

8. Series와 DataFrame에 외부 함수 적용하기

  • map 함수 : Series에서 사용하며 모든 요소에 함수 일괄 적용
  • apply 함수 : DataFrame에서 사용하며 각각의 행 또는 열(Series)에 함수 일괄 적용
  • applymap 함수 : DataFrame에서 사용하며 모든 요소에 함수 일괄 적용

8.1 Series의 각각의 요소에 함수 적용하기

map(Function name)

  • Series에서 사용가능한 함수
  • Series의 모든값(values)에 대해 입력된 함수 일괄 적용

pandas library import

import pandas as pd
from pandas import Series , DataFrame
srAge = Series([10,13,15,23,22,36])
srAge
0    10
1    13
2    15
3    23
4    22
5    36
dtype: int64

나이의 범위에 따라 10대, 20대, 30대로 변경하는 함수 생성

  • 10~19 : 10대
  • 20~29 : 20대
  • 30~39 : 30대
  • 그외 : NaN값

으로 변경

def weekday2weeknumber(age):
    if age >= 10 and age < 20:
        ageRange = '10대'
    elif age >= 20 and age < 30:
        ageRange = '20대'
    elif age >= 30 and age < 40:
        ageRange = '30대'
    else:
        ageRange = pd.np.nan
    return ageRange

map 함수로 Series의 각각의 값에 함수 적용

srAgeRange = srAge.map(weekday2weeknumber)
srAgeRange
0    10대
1    10대
2    10대
3    20대
4    20대
5    30대
dtype: object

8.2 DataFrame의 각 열 또는 행에 함수 일괄 적용하기

apply(Function name)

  • DataFrame에서 사용 가능한 함수
  • DataFrame의 행 또는 열에 해당하는 Series에 함수를 일괄 적용

axis 옵션

  • axis = 0(Defualt) : 열기준 함수 적용
  • axis = 1 : 행기준 함수 적용

DataFrame 생성

df = DataFrame([[1,3,5],[4,5,6],[7,8,10]])
df

0 1 2
0 1 3 5
1 4 5 6
2 7 8 10

행 또는 열의 최대값과 최소값의 차이를 구하는 함수 생성

def maxMinusMin(sr):
    return sr.max() - sr.min()
df.apply(maxMinusMin, axis = 0)
0    6
1    5
2    5
dtype: int64
df.apply(maxMinusMin, axis = 1)
0    4
1    2
2    3
dtype: int64

return값을 조정하여 여러개의 열 또는 컬럼으로 출력 가능

def maxMinusMin2(sr):
    sr2 = Series([sr.max(), sr.min(), sr.max()-sr.min()], index = ['최대값','최소값','차이'])
    return sr2
df.apply(maxMinusMin2, axis =0)

0 1 2
최대값 7 8 10
최소값 1 3 5
차이 6 5 5
df.apply(maxMinusMin2, axis =1)

최대값 최소값 차이
0 5 1 4
1 6 4 2
2 10 7 3

8.3 DataFrmae의 각각 요소에 함수 일괄 적용하기

applymap(Function name)

  • DataFrame에서 사용가능한 함수
  • DataFrame의 모든값(values)에 대해 함수 일괄 적용

DataFrame 생성

df2 = DataFrame([[1,1,1],[2,2,2],[3,3,3]])
df2

0 1 2
0 1 1 1
1 2 2 2
2 3 3 3

입력값의 제곱을 리턴하는 함수 생성

def square(x):
    y = x * x
    return y

df2.applymap(square)

0 1 2
0 1 1 1
1 4 4 4
2 9 9 9

위의 Jupyter notebook 내용은 여기 Github에서도 확인 할 수 있습니다.

감사합니다.

반응형
반응형

안녕하세요. PSYda입니다.

이번 포스팅에서는 Pandas DataFrame의 sort(정렬), rank(순위)에 대해 알아보겠습니다.

소개할 내용은 아래와 같습니다.

  • DataFrame의 정렬 함수(sort_values, sort_index)
  • DataFrame의 순위 측정 함수(rank)

실습에 사용한 데이터는 fifa19에 등장하는 축구선수들의 능력치 데이터 입니다.
아래에서 다운 받을 수 있습니다.

Ch6_1_fifaStats.csv
다운로드

7. DataFrame의 sort, rank 함수

  • sort 함수 : 데이터를 정렬하는 함수(sort_values, sort_index)
  • rank 함수 : 데이터의 순위를 매기는 함수

7.1 DataFrame의 sort

DataFrame에서는 sort를 index 및 column 기준으로 sort를 할 수 있다.

  • sort_values(axis = 0) : 열방향 정렬(default)
  • sort_values(axis = 1) : 행방향 정렬
  • sort_index(axis = 0) : 인덱스명 정렬(defualt)
  • sort_index(axis = 1) : 컬럼명 정렬

정렬은 ascending 옵션을 통해 오름차순과 내림차순 정렬이 가능하다.

  • ascending = True : 오름차순 정렬, 영어의 경우 a 부터
  • ascending = False : 내림차순 정렬, 영어의 경우 z부터

7.1.1 sort_values() : 열방향 또는 행방향 데이터 정렬

sort_values 함수 옵션

  • ascending = True : True 이면 오름차순, False이면 내림차순 정렬
  • inplace = False : True 이면 정렬한 값을 DataFrame에 바로 반영
  • by : 정렬할 기준 변수 지정
  • na_position = last : NaN값 위치 지정, last이면 마지막, first이면 처음
  • axis = 0 : 0이면 열방향 정렬, 1이면 행방향 정렬

pandas library import

import pandas as pd
from pandas import Series, DataFrame
import numpy as np
players = pd.read_csv('data/Ch6_1_fifaStats.csv', index_col = 'Name')
players.head()

ShortPassing Dribbling LongPassing BallControl
Name
L. Messi 90.0 97.0 87.0 96.0
Cristiano Ronaldo 81.0 88.0 77.0 94.0
Neymar Jr 84.0 96.0 78.0 95.0
De Gea 50.0 18.0 51.0 42.0
K. De Bruyne 92.0 86.0 91.0 91.0

7.1.1.1 by 옵션

DataFrame에서 정렬할 변수를 지정 할 수 있다.(Serise의 경우 한 컬럼이므로 by옵션 설정 필요 없음)

  • axis = 0 이면 컬럼명을 정렬 기준 변수로 지정(default)
  • axis = 1 이면 인덱스명을 정렬 기준 변수로 지정

ShortPassing 능력치 컬럼 기준 오름차순 정렬

players.sort_values(by = 'ShortPassing', axis = 0).head()

ShortPassing Dribbling LongPassing BallControl
Name
Deng Xiaofei 7.0 6.0 12.0 11.0
Zhang Chong 7.0 16.0 9.0 22.0
Cheng Yuelei 8.0 13.0 10.0 18.0
A. Donnarumma 11.0 19.0 11.0 23.0
Gabri Prestão 11.0 18.0 12.0 20.0

7.1.1.2 ascending 옵션

  • True(Default) : 오른차순 정렬
  • False : 내림차순 정렬,

ShortPassing 컬럼 기준 내림차순 정렬

players.sort_values(ascending = False,by = 'ShortPassing').head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 93.0 89.0 87.0 94.0
L. Modrić 93.0 90.0 88.0 93.0
T. Kroos 92.0 81.0 93.0 90.0
K. De Bruyne 92.0 86.0 91.0 91.0
C. Eriksen 91.0 84.0 88.0 91.0

7.1.1.3 na_position 옵션

  • 'last'(Defualt) : 결측값(NaN)을 뒤로 정렬
  • 'first' : 결측값(NaN)을 앞으로 정렬

ShortPassing 컬럼 기준 내림차순 정렬하면서 NaN을 처음에 배치

players.sort_values(ascending = False,by = 'ShortPassing', na_position='first').head()

ShortPassing Dribbling LongPassing BallControl
Name
J. McNulty NaN NaN NaN NaN
J. Barrera NaN NaN NaN NaN
J. Stead NaN NaN NaN NaN
A. Semprini NaN NaN NaN NaN
R. Bingham NaN NaN NaN NaN

7.1.1.4 inplace 옵션

  • False(Default) : 정렬된 내용을 단순 출력만함
  • True : 정렬된 내용을 DataFrame에 저장

players DataFrame에 정렬된 데이터를 저장

players.sort_values(ascending = False,by = 'ShortPassing', inplace = True)
players.head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 93.0 89.0 87.0 94.0
L. Modrić 93.0 90.0 88.0 93.0
T. Kroos 92.0 81.0 93.0 90.0
K. De Bruyne 92.0 86.0 91.0 91.0
C. Eriksen 91.0 84.0 88.0 91.0

7.1.1.5 axis 옵션

  • axis = 0 : 열방향으로 정렬(위에서 아래로)
  • axis = 1 : 행방향으로 정렬(좌에서 우로)

Index 명의 David Silva 기준으로 행방향 정렬

players.sort_values(axis = 1, by = 'David Silva').head()

LongPassing Dribbling ShortPassing BallControl
Name
David Silva 87.0 89.0 93.0 94.0
L. Modrić 88.0 90.0 93.0 93.0
T. Kroos 93.0 81.0 92.0 90.0
K. De Bruyne 91.0 86.0 92.0 91.0
C. Eriksen 88.0 84.0 91.0 91.0

7.1.2 sort_index() : 인덱스명 정렬

sort_index 함수의 옵션(sort_values 와 옵션이 거의 동일)

  • axis = 0(Default) : index명을 정렬
  • axis = 1 : 컬럼명을 정렬

A 부터 오름차순 정렬

players.sort_index().head()

ShortPassing Dribbling LongPassing BallControl
Name
A. Abang 52.0 56.0 28.0 59.0
A. Abdellaoui 53.0 39.0 45.0 47.0
A. Abdennour 58.0 48.0 62.0 51.0
A. Abdi 74.0 70.0 72.0 74.0
A. Abdu Jaber 49.0 61.0 40.0 59.0

내림차순 정렬

players.sort_index(ascending = False).head()

ShortPassing Dribbling LongPassing BallControl
Name
Óscar Whalley 32.0 16.0 30.0 18.0
Óscar Valentín 68.0 58.0 63.0 68.0
Óscar Plano 68.0 72.0 65.0 73.0
Óscar Pinchi 65.0 69.0 63.0 70.0
Óscar Gil 37.0 57.0 34.0 50.0

컬럼명 정렬

players.sort_index(axis = 1).head()

BallControl Dribbling LongPassing ShortPassing
Name
David Silva 94.0 89.0 87.0 93.0
L. Modrić 93.0 90.0 88.0 93.0
T. Kroos 90.0 81.0 93.0 92.0
K. De Bruyne 91.0 86.0 91.0 92.0
C. Eriksen 91.0 84.0 88.0 91.0

7.2 DataFrame의 rank

rank 함수 (데이터의 순위를 측정) 옵션

  • ascending : False 이면 숫자가 큰 것이 순위가 높음(rank 값이 작음)
  • axis : 0이면 열방향, 1이면 행방향으로 순위 측정
  • method : 동점인 경우 순위 측정에 사용할 방법(평균, 최소값, 최대값 등)
  • pct : True 이면 상위 몇% 인지 보여줌

7.2.1 ascending 옵션

  • True(Default) : 데이터 수치가 클 수록 rank값이 커짐(순위가 낮아짐)
  • False : 데이터 수치가 작을 수록 rank값이 작아짐(순위가 높아짐)

컬럼별로 순위 측정(데이터 수치가 클수록 rank가 높음)

players.rank().head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 18158.5 18131.5 18145.0 18155.0
L. Modrić 18158.5 18141.5 18150.5 18152.5
T. Kroos 18156.5 17790.5 18159.0 18137.5
K. De Bruyne 18156.5 18061.0 18158.0 18145.0
C. Eriksen 18155.0 17982.5 18150.5 18145.0
players.rank(ascending = False).head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 1.5 28.5 15.0 5.0
L. Modrić 1.5 18.5 9.5 7.5
T. Kroos 3.5 369.5 1.0 22.5
K. De Bruyne 3.5 99.0 2.0 15.0
C. Eriksen 5.0 177.5 9.5 15.0

7.2.2 axis 옵션

  • axis = 0(Defualt) : 열방향으로 순위 측정
  • axis = 1 : 행방향으로 순위 측정

행방향으루 순위 측정(David Silva의 경우 BallControl 컬럼의 순위가 가장 높음)

players.rank(ascending = False, axis = 1).head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 2.0 3.0 4.0 1.0
L. Modrić 1.5 3.0 4.0 1.5
T. Kroos 2.0 4.0 1.0 3.0
K. De Bruyne 1.0 4.0 2.5 2.5
C. Eriksen 1.5 4.0 3.0 1.5

7.2.3 method 옵션

데이터 수치가 동점일 경우 순위 측정 방법

  • average(Default) : 평균으로 순위 측정( Ex. 1위가 2명인경우 1.5 )
  • first : 동점없이 정렬된 순서대로 순위 측정( Ex. 1위가 3명인 경위 위에서부터 1,2,3 )
  • max : 동점인 데이터들 중 순위가 낮은 값 선정( Ex. 1위가 3명인 경우 3 )
  • min : 동점인 데이터들 중 순위가 높은 값 선정( Ex. 1위가 3명인 경우 1등, 4번째 데이터의 경우 4등 )
  • dense : min과 비슷하지만 동점 다음 데이터 순위 측정에서 차이가 있음( Ex. 1위가 3명인 경우 1등, 4번째 데이터의 경우 2등 )

순위가 동점이면 평균값 측정(David Silva와 L.Modric이 공동 1등이므로 1.5값 부여)

players.rank(ascending = False, method = 'average').head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 1.5 28.5 15.0 5.0
L. Modrić 1.5 18.5 9.5 7.5
T. Kroos 3.5 369.5 1.0 22.5
K. De Bruyne 3.5 99.0 2.0 15.0
C. Eriksen 5.0 177.5 9.5 15.0
players.rank(ascending = False, method = 'first').head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 1.0 25.0 11.0 4.0
L. Modrić 2.0 13.0 9.0 7.0
T. Kroos 3.0 332.0 1.0 18.0
K. De Bruyne 4.0 80.0 2.0 13.0
C. Eriksen 5.0 153.0 10.0 14.0
players.rank(ascending = False, method = 'max').head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 2.0 32.0 19.0 6.0
L. Modrić 2.0 24.0 10.0 8.0
T. Kroos 4.0 407.0 1.0 27.0
K. De Bruyne 4.0 118.0 2.0 17.0
C. Eriksen 5.0 202.0 10.0 17.0
players.rank(ascending = False, method = 'min').head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 1.0 25.0 11.0 4.0
L. Modrić 1.0 13.0 9.0 7.0
T. Kroos 3.0 332.0 1.0 18.0
K. De Bruyne 3.0 80.0 2.0 13.0
C. Eriksen 5.0 153.0 9.0 13.0
players.rank(ascending = False, method = 'dense').head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 1.0 9.0 6.0 3.0
L. Modrić 1.0 8.0 5.0 4.0
T. Kroos 2.0 17.0 1.0 7.0
K. De Bruyne 2.0 12.0 2.0 6.0
C. Eriksen 3.0 14.0 5.0 6.0

7.2.4 pct 옵션

  • False(Default) : rank를 순위(숫자)로 매김
  • True : 순위의 퍼센테이지값으로 매김(ex. 4명 중 1등인 경우 0.25, 4등은 1.0)

players 데이터 확인

players.head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 93.0 89.0 87.0 94.0
L. Modrić 93.0 90.0 88.0 93.0
T. Kroos 92.0 81.0 93.0 90.0
K. De Bruyne 92.0 86.0 91.0 91.0
C. Eriksen 91.0 84.0 88.0 91.0

행방향으로 퍼센테이지 순위 측정(David Silva의 경우 BallControl이 1등이므로 0.25)

players.rank(ascending = False, axis = 1, pct = True).head()

ShortPassing Dribbling LongPassing BallControl
Name
David Silva 0.500 0.75 1.000 0.250
L. Modrić 0.375 0.75 1.000 0.375
T. Kroos 0.500 1.00 0.250 0.750
K. De Bruyne 0.250 1.00 0.625 0.625
C. Eriksen 0.375 1.00 0.750 0.375

위의 Jupyter notebook 내용은 여기 Github에서도 확인 할 수 있습니다.

감사합니다.

반응형
반응형

안녕하세요. PSYda입니다.

이번 포스팅에서는 Pandas DataFrame의 통계에 대해 알아보겠습니다.

소개할 내용은 아래와 같습니다.

  • DataFrame의 통계 함수 소개(주요통계량 출력, 평균, 표준편차, 최대/최소값, 상관계수 등)
  • DataFame의 통계에 대한 시각화(히스토그램, 상관관계)

실습에 사용한 데이터는 fifa19에 등장하는 선술들의 능력치 데이터 입니다.
아래에서 다운로드 받을 수 있습니다.

Ch6_1_fifaStats.csv
다운로드

6.Pandas DataFrame 통계

DataFrame의 주요한 통계 함수는 아래와 같습니다.

  • Describe : 전체 주요 통계량 출력
  • sum : 합계 출력
  • cumsum : 누적합계 출력
  • mean : 평균값 출력
  • Std : 표준 편차 출력
  • var : 분산 출력
  • median : 중앙값 출력
  • count : 데이터 개수 출력
  • min, max, idxmin, idxmax : 최소값,최대값,최소값의 index, 최대값의 index 출력
  • corr, cov : 상관계수, 공분산 출력

위의 통계 함수를 비롯한 대부분의 함수에서 axis 옵션을 이용해 사용할 축을 설정할 수 있습니다.

  • axis = 0 : 열방향으로 통계량 산출(Default)
  • axis = 1 : 행방향으로 통계량 산출

실습을 위해 Fifa19 선수들의 Stat 정보를 Load

import pandas as pd
from pandas import Series, DataFrame
import numpy as np
players = pd.read_csv('data/Ch6_1_fifaStats.csv', index_col = 'Name')
players.head()

ShortPassing Dribbling LongPassing BallControl
Name
L. Messi 90.0 97.0 87.0 96.0
Cristiano Ronaldo 81.0 88.0 77.0 94.0
Neymar Jr 84.0 96.0 78.0 95.0
De Gea 50.0 18.0 51.0 42.0
K. De Bruyne 92.0 86.0 91.0 91.0

6.1 전체 통계량 요약 보기(describe)

describe 함수 : 컬럼별 전체 통계량을 요약해서 볼 수 있음

  • 데이터 개수, 평균, 표준편차, 최소값, 4분위값, 최대값 출력
  • 숫자형 컬럼만 통계량을 출력함

decribe 함수 호출

players.describe()

ShortPassing Dribbling LongPassing BallControl
count 18159.000000 18159.000000 18159.000000 18159.000000
mean 58.686712 55.371001 52.711933 58.369459
std 14.699495 18.910371 15.327870 16.686595
min 7.000000 4.000000 9.000000 5.000000
25% 54.000000 49.000000 43.000000 54.000000
50% 62.000000 61.000000 56.000000 63.000000
75% 68.000000 68.000000 64.000000 69.000000
max 93.000000 97.000000 93.000000 96.000000

6.2 함수별 통계량 보기

6.2.1 sum():합계 출력

players.sum()
ShortPassing    1065692.0
Dribbling       1005482.0
LongPassing      957196.0
BallControl     1059931.0
dtype: float64

6.2.2 cumsum():누적합계 출력

# 선수별 능력치 누적 합계 출력
players.head().cumsum(axis = 1)

ShortPassing Dribbling LongPassing BallControl
Name
L. Messi 90.0 187.0 274.0 370.0
Cristiano Ronaldo 81.0 169.0 246.0 340.0
Neymar Jr 84.0 180.0 258.0 353.0
De Gea 50.0 68.0 119.0 161.0
K. De Bruyne 92.0 178.0 269.0 360.0

6.2.3 mean(): 평균값 출력

Stat별 평균(컬럼 기준)

players.mean()
ShortPassing    58.686712
Dribbling       55.371001
LongPassing     52.711933
BallControl     58.369459
dtype: float64

선수별 평균(행 기준)

players.mean(axis=1).head()
Name
L. Messi             92.50
Cristiano Ronaldo    85.00
Neymar Jr            88.25
De Gea               40.25
K. De Bruyne         90.00
dtype: float64

6.2.4 std(): 표준편차 출력

players.std()
ShortPassing    14.699495
Dribbling       18.910371
LongPassing     15.327870
BallControl     16.686595
dtype: float64

6.2.5 var():분산 출력

players.var()
ShortPassing    216.075157
Dribbling       357.602135
LongPassing     234.943613
BallControl     278.442466
dtype: float64
```text


### 6.2.6 median():중앙값 출력


```python
players.median()
ShortPassing    62.0
Dribbling       61.0
LongPassing     56.0
BallControl     63.0
dtype: float64

6.2.7 count() : 데이터 개수 출력

players.count()
ShortPassing    18159
Dribbling       18159
LongPassing     18159
BallControl     18159
dtype: int64

6.2.8 max(), min() : 최대값, 최소값 출력

players.max()
ShortPassing    93.0
Dribbling       97.0
LongPassing     93.0
BallControl     96.0
dtype: float64
players.min()
ShortPassing    7.0
Dribbling       4.0
LongPassing     9.0
BallControl     5.0
dtype: float64

6.2.9 idxmin(), idxmax():최대값,최소값에 해당하는 인덱스 출력

선수별 가장 낮은 능력치는?

players.idxmin(axis = 1).head()
Name
L. Messi             LongPassing
Cristiano Ronaldo    LongPassing
Neymar Jr            LongPassing
De Gea                 Dribbling
K. De Bruyne           Dribbling
dtype: object

스탯별 최고의 선수는?

players.idxmax()
ShortPassing    L. Modrić
Dribbling        L. Messi
LongPassing      T. Kroos
BallControl      L. Messi
dtype: object

6.2.10 corr(), cov(): 상관계수, 공분산 출력

전체 컬럼별 상관계수 행렬 출력

corr_mat = players.corr()
corr_mat

ShortPassing Dribbling LongPassing BallControl
ShortPassing 1.000000 0.843722 0.895722 0.911451
Dribbling 0.843722 1.000000 0.722465 0.938942
LongPassing 0.895722 0.722465 1.000000 0.788650
BallControl 0.911451 0.938942 0.788650 1.000000

특정 컬럼과 상관도가 높은 순서대로 출력

corr_mat['ShortPassing'].sort_values(ascending = False)
ShortPassing    1.000000
BallControl     0.911451
LongPassing     0.895722
Dribbling       0.843722
Name: ShortPassing, dtype: float64

전체 컬럼별 공분산 행렬 출력

cov_mat = players.cov()
cov_mat

ShortPassing Dribbling LongPassing BallControl
ShortPassing 216.075157 234.531811 201.816840 223.564867
Dribbling 234.531811 357.602135 209.410657 296.282958
LongPassing 201.816840 209.410657 234.943613 201.712999
BallControl 223.564867 296.282958 201.712999 278.442466

특정 컬럼과 공분산이 낮은 순서대로 출력

cov_mat['Dribbling'].sort_values(ascending = True)
LongPassing     209.410657
ShortPassing    234.531811
BallControl     296.282958
Dribbling       357.602135
Name: Dribbling, dtype: float64

6.3 통계량 시각화하기

6.3.1 histogram 시각화

players.hist(figsize = (15,10))
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6CA2E6A0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6CA2D898>],
        [<matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6C860080>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6C8872E8>]],
      dtype=object)

6.3.2 상관계수 그래프 시각화

pd.plotting.scatter_matrix(players, figsize = (15,10))
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E38F1D0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E6F50B8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E3D6358>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E3FD898>],
        [<matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E426E10>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E4573C8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E47F940>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E4A8EF0>],
        [<matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E4A8F28>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E4FE9E8>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E525F60>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E556518>],
        [<matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E580A90>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E5B2048>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E5D95C0>,
        <matplotlib.axes._subplots.AxesSubplot object at 0x0000020A6E601B38>]],
      dtype=object)

위의 Jupyter notebook 내용은 여기 Github에서도 확인 할 수 있습니다.

감사합니다.

반응형
반응형

안녕하세요. PSYda입니다.

이번 포스팅에서는 Pandas DataFrame의 산술 연산에 대해 알아보겠습니다.

소개할 내용은 아래와 같습니다.

  • DataFrame과 DataFrame의 연산 함수 소개
  • DataFrame과 Sereis의 연산 함수 소개

5.Pandas DataFrame 산술 연산

DataFrame 의 연산은 아래의 두 가지 케이스가 있습니다.

  • DataFrame vs DataFrame 연산
  • DataFrame vs Series 연산

5.1 DataFrame vs DataFrame 연산

DataFrame의 연산 규칙은 아래와 같습니다.

  • 같은 index 이면서 같은 column 명을 가진 두 value를 연산함
  • 같은 index 이면서 같은 column 명을 가진 두 value 중 하나라도 NaN이 있으면 NaN으로 채워진다.
  • index나 column 명이 다르면 NaN으로 채워진다.

연산하는 방법에는 두 가지 방법이 있습니다.

  • 연산자( +, -, *, / )를 이용한 연산
  • 함수( add, sub, mul, div )를 이용한 연산

기본 연산은 동일하지만 함수를 사용하면 fill_valueaxis 옵션을 사용할 수 있습니다.

Ex)df1.add(df2, fill_value = 0, axis = 0)

  • fill_value = 0 : NaN값을 0으로 간주하고 연산, 0이 아닌 값 입력 가능
  • axis = 0 : DataFrame와 Series간의 연산에서 방향을 지정(5.1.2 참고)

곱하기, 나누기, 빼기 등도 동일한 방법이므로, 대표로 더하기에 대해서만 실습해보겠습니다.

import pandas as pd
from pandas import Series, DataFrame
import numpy as np
df1 = DataFrame([[1,3,5],[7,9,11],[5,13,15]])
df1

0 1 2
0 1 3 5
1 7 9 11
2 5 13 15
df2 = DataFrame([[1,2,3],[4,np.nan,6],[7,8,9]], columns=[0,1,3], index=[0,1,3])
df2

0 1 3
0 1 2.0 3
1 4 NaN 6
3 7 8.0 9
df1 + df2

0 1 2 3
0 2.0 5.0 NaN NaN
1 11.0 NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN NaN NaN NaN
df1.add(df2,fill_value=0)

0 1 2 3
0 2.0 5.0 5.0 3.0
1 11.0 9.0 11.0 6.0
2 5.0 13.0 15.0 NaN
3 7.0 8.0 NaN 9.0

5.2 DataFrame vs Series 연산

연산 함수(add, sub, mul, div) 의 axis 옵션을 통해 행, 열 방향으로 연산 가능

Ex) df1.add(df2, axis = 0)

axis = 0 : Index방향(행방향)으로 DataFrame과 Series 연산

  • DataFrame과 Series가 동일한 Index를 가지면 연산, 다르면거나 한쪽만 있으면 NaN

axis = 1 : Column방향으로 DataFrame과 Series 연산

  • DataFrame과 Series가 동일한 Column명을 가지면 연산, 다르면거나 한쪽만 있으면 NaN

연산을 위한 Sereis 생성

s1 = Series([1,2,3,4])
s1
0    1
1    2
2    3
3    4
dtype: int64
df1

0 1 2
0 1 3 5
1 7 9 11
2 5 13 15
df1.add(s1, axis = 0)

0 1 2
0 2.0 4.0 6.0
1 9.0 11.0 13.0
2 8.0 16.0 18.0
3 NaN NaN NaN
df1.add(s1, axis = 1)

0 1 2 3
0 2 5 8 NaN
1 8 11 14 NaN
2 6 15 18 NaN

위의 Jupyter notebook 내용은 여기 Github에서도 확인 할 수 있습니다,

다음 포스팅은 DataFrame의 통계에 대해 알아볼 예정입니다.

감사합니다.

반응형
반응형

안녕하세요. PSYda입니다.

이번 포스팅에서는 Pandas 데이터의 파일 입출력 방법에 대해 알아보겠습니다.

실습에 필요한 파일은 아래에서 다운로드 받을 수 있습니다.

data.zip
다운로드

소개할 내용은 아래와 같습니다.

  • 텍스트 파일 입력을 위한 read_csv 함수 소개
  • 엑셀 파일 입력을 위한 read_excel 함수 소개
  • DataFrame의 텍스트 파일 출력을 위한 to_csv 함수 소개
  • DataFrame의 엑셀 파일 출력을 위한 to_excel 함수 소개

4. Pandas 파일 입출력

Pandas로 입출력 할 수 있는 파일 포맷은 매우 다양하지만 대표적으로 아래와 같습니다.

  • CSV, Excel, HTML, JSON 등

이번에는 CSV 및 Excel File을 입출력하는 방법을 알아보겠습니다.

예제에 사용하기 위한 데이터를 확보하기 위해 kaggle에서 fifa19 선수 Dataset을 다운로드 받았으며, 실습에 사용하기 위해 변형하였습니다.

4.1 파일 입력

4.1.1 (구분자가 있는)텍스트 파일 및 CSV 파일 읽기

Pandas에서 read_csv 함수를 이용하여 텍스트 파일 및 CSV 파일을 읽을 수 있으며, 읽은 데이터는 DataFrame형태로 저장됩니다.
read_csv 함수 사용법은 아래와 같습니다.

pd.read_csv(FilePath, sep, header, names, index_col, skiprows, nrows, encoding, comment, chunksize)

  • FilePath : 읽을 파일 Path, URL 도 가능
  • sep : 구분자 입력, Default 는 쉼표(',')
  • header : 파일의 데이터에 header가 없을 경우 none 입력, Default는 header 읽음
  • names : 파일의 데이터에 header가 없을 경우에 명시적으로 컬럼명 입력 가능
  • skiprows : 입력한 개수 만큼 파일에서 행을 건너뛰고 읽음
  • index_col : 명시한 특정 컬럼을 index로 사용
  • nrows : 파일 최상위에서부터 입력한 개수만큼의 데이터만 읽음
  • encoding : 파일의 문자 인코딩 타입 입력, 한글이면 'CP949'
  • comment : 특정 문자는 주석으로 간주하고 읽지 않음
  • chunksize : TextFileReader가 입력받을 데이터 개수 Return하여 특정 개수 만큼 순서대로 읽음(뒤에 예시 참고)

pandas libary를 import

import pandas as pd
from pandas import Series, DataFrame

4.1.1.1 read_csv(별도 옵션 없이)

  • 일반 text 파일 또는 csv을 읽어서 DataFrame에 저장
  • 쉼표(',')를 기준으로 Data를 나누고 읽음

별도의 설정 없이 csv File 읽기

fifa19Player = pd.read_csv("data/Ch4_1_fifa.csv")
fifa19Player.head(5)

Index ID Name Age
0 0 158023 L.Messi 31
1 1 20801 CristianoRonaldo 33
2 2 190871 NeymarJr 26
3 3 193080 DeGea 27
4 4 192985 K.DeBruyne 27

4.1.1.2 sep 옵션

  • 공백, 탭, 다른 기호 등으로 데이터가 분리된 파일일 경우 사용
  • 공백의 경우 정규식 '\s+' 을 사용함(공백이 하나 이상 발생한 경우 구분하는 정규식)

구분자를 공백으로 주고 csv File 읽기

data1 = pd.read_csv('data/Ch4_2_sep.txt', sep='\s+')
data1

Index ID Name Age
0 0 158023 L.Messi 31
1 1 20801 CristianoRonaldo 33
2 2 190871 NeymarJr 26
3 3 193080 DeGea 27
4 4 192985 K.DeBruyne 27

4.1.1.3 header 옵션

  • Default 값은 첫 행을 Header로 간주
  • 첫 행이 Header가 아닐 경우 None 을 입력해주면, 첫 행도 데이터로 저장
  • 왼쪽부터 0부터 순서대로 컬럼명 부여

header가 없는 File 읽기

data2 = pd.read_csv('data/Ch4_3_header.txt', sep='\s+', header = None)
data2

0 1 2 3
0 0 158023 L.Messi 31
1 1 20801 CristianoRonaldo 33
2 2 190871 NeymarJr 26
3 3 193080 DeGea 27
4 4 192985 K.DeBruyne 27

4.1.1.4 names 옵션

  • 첫 행이 Header가 아닐 경우 명시적으로 컬럼명 입력 가능

header가 없응 File 읽을 때 컬럼명 명시

data3 = pd.read_csv('data/Ch4_3_header.txt', sep='\s+', names = ['Index', 'ID', 'Player', 'Age'])
data3

Index ID Player Age
0 0 158023 L.Messi 31
1 1 20801 CristianoRonaldo 33
2 2 190871 NeymarJr 26
3 3 193080 DeGea 27
4 4 192985 K.DeBruyne 27

4.1.1.5 skiprosw 옵션

  • 읽고 싶지 않은 행(MetaData 등)을 제외 할 수 있음
  • 특정 행을 읽는데 에러가 생기는 경우 제외 할 수 있음

특정 행을 제외하고 파일 읽기

data4 = pd.read_csv("data/Ch4_4_skiprows.txt", sep='\s+', skiprows = [0,1], header = None)
data4

0 1 2 3
0 0 158023 L.Messi 31
1 1 20801 CristianoRonaldo 33
2 2 190871 NeymarJr 26
3 3 193080 DeGea 27
4 4 192985 K.DeBruyne 27

4.1.1.6 index_col 옵션

  • 특정 컬럼명을 Index열로 저장

index 컬럼을 Index로 설정

data5 = pd.read_csv('data/Ch4_5_index_col.txt', index_col = 'Index')
data5

ID Name Age
Index
0 158023 L.Messi 31
1 20801 CristianoRonaldo 33
2 190871 NeymarJr 26
3 193080 DeGea 27
4 192985 K.DeBruyne 27

4.1.1.7 nrows 옵션

  • 위에서부터 입력한 개수 만큼의 데이터만 읽음
  • 데이터량이 많아 메모리에 문제가 예상될 때 사용 할 수 있음

3개의 row만 읽기

data6= pd.read_csv('data/Ch4_5_index_col.txt', nrows = 3)
data6

Index ID Name Age
0 0 158023 L.Messi 31
1 1 20801 CristianoRonaldo 33
2 2 190871 NeymarJr 26

4.1.1.8 encoding 옵션

  • 데이터 encoding 이 맞지 않아 문자가 깨지거나 오류가 생길 때 설정
  • 한글의 경우 'CP949' 를 적용하면 깨지지 않음

CP949 encoding 적용!

data7= pd.read_csv('data/Ch4_6_encoding.txt', encoding = 'CP949')
data7

Index ID 이름 나이
0 0 158023 L.Messi 31
1 1 20801 CristianoRonaldo 33
2 2 190871 NeymarJr 26
3 3 193080 DeGea 27
4 4 192985 K.DeBruyne 27

4.1.1.9 comment 옵션

  • 특정 문자가 있는 행은 주석으로 간주하고 읽지 않고 건너뜀

'/' 문자는 주석이므로 읽기 않음

data5 = pd.read_csv('data/Ch4_5_comment.txt', comment = '/')
data5

Index ID Name Age
0 0 158023 L.Messi 31
1 1 20801 CristianoRonaldo 33
2 2 190871 NeymarJr 26
3 3 193080 DeGea 27
4 4 192985 K.DeBruyne 27

4.1.1.10 chunksize 옵션

  • 특정 개수만큼 순서대로 입력 받을 수 있는 TextFileReader 객체를 생성
  • next(TextFileReader객체) 구문을 이용해 특정 개수만큼 순서대로 데이터 입력
  • 데이터량이 많아서 한번에 불러올 수 없는 경우에 사용

2개씩 데이터 입력

TextFileReader = pd.read_csv('data/Ch4_1_fifa.csv', chunksize = 2)
next(TextFileReader)

Index ID Name Age
0 0 158023 L.Messi 31
1 1 20801 CristianoRonaldo 33
# 한번 더 하면 그 다음 500개 가 순서대로 출력
next(TextFileReader)

Index ID Name Age
2 2 190871 NeymarJr 26
3 3 193080 DeGea 27

4.1.2 Excel 파일 읽기

read_excel 함수를 이용하여 excel 파일을 읽어 올 수 있으며 대부분의 옵션들은 read_csv와 동일합니다.

자주 사용되는 옵션들 위주로 알아보겠습니다.

read_excel(Path, sheet_name)

  • Path : excel 파일 경로
  • sheet_name : 읽을 Sheet name 명시

4.1.2.1 read_excel(별도 옵션 없이)

fifa = pd.read_excel('data/Ch4_9_fifa19.xlsx')
fifa

Unnamed: 0 ID Name Age
0 0 158023 L. Messi 31
1 7 176580 L. Suárez 31
2 18 192448 M. ter Stegen 26
3 20 189511 Sergio Busquets 29
4 32 189242 Coutinho 26

4.1.2.2 sheet_name

  • 명시한 Sheet name만 읽음
  • Default는 첫 번째 Sheet
  • None을 입력하면 모든 Sheet를 key = Sheetname, value = Data 로 가져옴

Tottenham sheet 읽기

Tottenham = pd.read_excel('data/Ch4_9_fifa19.xlsx', sheet_name = 'Tottenham')
Tottenham

Unnamed: 0 ID Name Age
0 16 202126 H. Kane 24
1 31 190460 C. Eriksen 26
2 37 167948 H. Lloris 31
3 125 200104 H. Son 25
4 71 184087 T. Alderweireld 29
AllTeam = pd.read_excel('data/Ch4_9_fifa19.xlsx', sheet_name = None)
AllTeam.keys()
odict_keys(['FCBarcelona', 'Tottenham', 'ManUnited'])
AllTeam['ManUnited']

Unnamed: 0 ID Name Age
0 3 193080 De Gea 27
1 45 195864 P. Pogba 25
2 47 192505 R. Lukaku 25
3 93 184941 A. Sánchez 29
4 116 211300 A. Martial 22

한번에 세 개의 팀을 저장 할 수도 있음

Barcelona, Tottenham, ManUTD = AllTeam.values()
Tottenham

Unnamed: 0 ID Name Age
0 16 202126 H. Kane 24
1 31 190460 C. Eriksen 26
2 37 167948 H. Lloris 31
3 125 200104 H. Son 25
4 71 184087 T. Alderweireld 29

4.2 파일 출력

파일 입력과 마찬가지로 Pandas는 다양한 데이터로의 출력을 지원하지만 가장 많이 사용하는 csv, excel 에 관해서만 알아보겠습니다.

4.2.1 (구분자가 있는)텍스트 파일 및 CSV 로 출력

Pandas에서는 DataFame 데이터를 to_csv 함수를 이용하여 텍스트 파일 및 CSV 파일로 출력할 수 있습니다.

to_csv도 read_csv와 비슷한 옵션들을 가지고 있기 떄문에, 옵션에 대한 설명은 넘어가도록 하겠습니다.

Tottenham.to_csv('data/Tottenham.csv')

4.2.2 Excel 로 출력

to_excel 함수를 이용해 DataFrame 데이터를 Excel 파일로 출력할 수 있습니다.

마찬가지로 옵션에 대한 설명은 넘어가도록 하겠습니다.

ManUTD.to_excel('data/ManUTD.xlsx')

위의 Jupyter notebook 내용은 여기 Github에서도 확인 할 수 있습니다.

감사합니다.

반응형
반응형

안녕하세요. PSYda 입니다.

이번 포스팅에서는 두 개의 DataFrame을 연결하는 Join 기법에 대해 알아보겠습니다.

소개할 내용은 아래와 같습니다.

  • 컬럼 기준 Join
  • Index 기준 Join
  • 행기준 Join
  • Inner, Left, Right ,Outer Join

3. DataFrame Join

Join 이란?

  • 두 개의 DataFrame을 합치는 것
  • 열기준 컬럼명으로 합치기 : merge
  • 열기준 Index명로 합치기 : merge, concat
  • 행기준으로 합치기 : concat, append

합치는 방법은?

  • Inner : 두 DataFrame의 기준 컬럼에서 둘 다 존재하는 데이터만 Join
  • Left Outer join : 왼쪽 DataFrame으로 합치기
  • Right Outer Join : 오른쪽 DataFrame으로 합치기
  • Outer Join : 두 DataFrame의 모든 Data를 합치기

Merge 명령어 사용법?

  • pd.merge(left, right, how, on, left_on, right_on, left_index, right_index)
  • left : Merge 할 왼쪽 DataFrame
  • right : Merge 할 오른쪽 DataFrame
  • how : inner, left, right, outer
  • on : 두 DataFrame을 Join할 기준 컬럼명(컬럼명이 동일할 경우)
  • left_on : Join할 기준 컬럼의 왼쪽 DataFrame의 컬럼명
  • right_on : Join할 기준 컬럼의 오른쪽 DataFrame의 컬럼명
  • left_index : 왼쪽 DataFrame index로 Join할 경우 True
  • right_index : 오른쪽 DataFrame index로 Join할 경우 True

concat 명령어 사용법?

  • pd.concat([left,right], axis, join,...)
  • [left,right] : left DataFrame과 right DataFrame으로 이루어진 List
  • axis = 0 : 행기준으로 합치기, 1: 열기준으로 Index명으로 합치기

pandas libary를 import 합니다.

import pandas as pd
from pandas import Series, DataFrame

3.1 같은 Column끼리 합치기

DF1 = DataFrame([["싸이",180,75],["덕구",160,65],["또치",170,75]], columns = ["이름","키","몸무게"])
DF1

이름 몸무게
0 싸이 180 75
1 덕구 160 65
2 또치 170 75
DF2 = DataFrame([["싸이","포워드","잘함"],["덕구","미드필더","못함"],["똥갈","수비수","잘함"]], columns = ["이름","포지션","실력"])
DF2

이름 포지션 실력
0 싸이 포워드 잘함
1 덕구 미드필더 못함
2 똥갈 수비수 잘함

3.1.1 Inner Join

두 DataFrame의 기준 컬럼에서 둘 다 존재하는 데이터만 Join

pd.merge(left = DF1 , right = DF2, how = "inner", on = "이름")

이름 몸무게 포지션 실력
0 싸이 180 75 포워드 잘함
1 덕구 160 65 미드필더 못함

3.1.2 Left Outer Join

  • 왼쪽 DataFrame의 모든 데이터 출력 +
  • 오른쪽 DataFrame 중 왼쪽 DataFrame에 있는 Data는 출력
  • 오른쪽 DataFrame 중 왼쪽 DataFrame에 없는 Data는 NaN으로 처리

pd.merge(left = DF1 , right = DF2, how = "left", on = "이름")

몸무게 포지션 실력
이름
싸이 180 75 포워드 잘함
덕구 160 65 미드필더 못함
또치 170 75 NaN NaN

3.1.3 Right Outer Join

  • 오른쪽 DataFrame의 모든 데이터 출력 +
  • 왼쪽 DataFrame 중 오른쪽 DataFrame에 있는 Data는 출력
  • 왼쪽 DataFrame 중 오른쪽 DataFrame에 없는 Data는 NaN으로 처리

pd.merge(left = DF1 , right = DF2, how = "right", on = "이름")

이름 몸무게 포지션 실력
0 싸이 180.0 75.0 포워드 잘함
1 덕구 160.0 65.0 미드필더 못함
2 똥갈 NaN NaN 수비수 잘함

3.1.4 Outer Join

  • 왼쪽, 오른쪽 DataFrame의 모든 데이터 출력 +
  • 왼쪽 DataFrame 중 오른쪽 DataFrame에 있는 Data는 NaN으로 처리
  • 오른쪽 DataFrame 중 왼쪽 DataFrame에 없는 Data는 NaN으로 처리

DF1과 DF2를 Outer Join

pd.merge(left = DF1 , right = DF2, how = "outer", on = "이름")

이름 몸무게 포지션 실력
0 싸이 180.0 75.0 포워드 잘함
1 덕구 160.0 65.0 미드필더 못함
2 또치 170.0 75.0 NaN NaN
3 똥갈 NaN NaN 수비수 잘함

3.2 같은 Index 기준으로 합치기

  • set_index("컬럼명") : 컬럼명의 데이터가 Index로 설정, 컬럼데이터는 삭제
DF1 = DF1.set_index("이름")
DF1

몸무게
이름
싸이 180 75
덕구 160 65
또치 170 75
DF2 = DF2.set_index("이름")
DF2

포지션 실력
이름
싸이 포워드 잘함
덕구 미드필더 못함
똥갈 수비수 잘함
pd.merge(left = DF1, right = DF2, left_index = True, right_index = True, how = "inner")

몸무게 포지션 실력
이름
싸이 180 75 포워드 잘함
덕구 160 65 미드필더 못함
pd.concat([DF1,DF2],axis = 1, join = 'inner')

몸무게 포지션 실력
이름
싸이 180 75 포워드 잘함
덕구 160 65 미드필더 못함

3.3 행기준으로 합치기

  • 같은 컬럼명이 존재하면, 데이터 저장
  • 다른 컬럼명이 존재하면, 해당 컬럼이 있는 DataFrame은 데이터 저장, 없는 DataFrame은 NaN 처리
  • 일반적으로 concat보다 append가 더 빠름
DF3 = DataFrame([[187, 80, 30], [190,85, 20]], columns = ["키","몸무게","나이"], index = ["거북이","깜디"])
DF3

몸무게 나이
거북이 187 80 30
깜디 190 85 20
DF1.append(DF3, sort=False)

몸무게 나이
싸이 180 75 NaN
덕구 160 65 NaN
또치 170 75 NaN
거북이 187 80 30.0
깜디 190 85 20.0
pd.concat([DF1, DF3], axis = 0, sort=False)

몸무게 나이
싸이 180 75 NaN
덕구 160 65 NaN
또치 170 75 NaN
거북이 187 80 30.0
깜디 190 85 20.0

위의 Jupyter notebook 내용은 여기 Github에서도 확인 할 수 있습니다.

다음 포스팅은 Pandas 데이터의 파일 입출력에 대해 알아볼 예정입니다.

감사합니다.

반응형

+ Recent posts

반응형