이번 포스팅에서는 lambda 를 사용한 이름이 없는 익명 함수(the anonymous functions), 한 줄로 간단하게 다음 함수 안에 넣어서 사용할 수 있는 인 라인 함수 (inline functions)에 대해서 알아보겠습니다. 


R 사용하다가 Python 넘어올 때 처음으로 lambda 익명함수를 봤을 때 '이게 뭔가?' 했었는데요, 아래의 예제들을 같이 살펴보시면 어렵지 않게 이해할 수 있을 겁니다. 





(1) 익명 함수 (the anonymous functions) lambda 


이전 포스팅에서 소개했던 def function_name(argments): expression return result; 형태의 함수 정의와는 다르게, 함수의 이름 부여 없이도 lambda 를 사용하면 함수를 정의할 수 있습니다. 



[ lambda 함수 문법 ]

lambda arg1, agr2, ... arg n: expression

 


아래는 input으로 받은 숫자를 제곱해주는 함수를 def 와 lambda 로 각각 정의해 본 예제입니다. 


lambda 익명함수 정의는 한줄 짜리 간단한 함수를 작성해서 편하게 쓴다든지, 메모리를 아끼고 가독성을 높이는데 유용하게 쓸 수 있습니다. (lambda는 이름 없는 익명함수이기 때문에 한번 실행되고 다음줄로 넘어가면 heap 메모리 영역에서 증발되므로 메모리를 아낄 수 있습니다.)


def 를 사용한 이름을 가진 함수 정의

lambda 를 사용한 이름 없는(익명) 함수 정의

 

In [1]: def my_pow(x):

   ...:     result = x**2

   ...:     return result;


In [2]: my_pow(3)

Out[2]: 9


[3]: my_pow2 = lambda x: x**2


In [4]: my_pow2(3)

Out[4]: 9




다음으로 List, Tuple, String과 같은 순서열 데이터에 대해 lambda 함수와 함께 map(), filter(), reduce(), apply() 함수의 안에 익명 함수로 INLINE으로 사용하는 예제, 리스트 축약(list comprehension) 도 더불어 소개하겠습니다.  



 (2) map(lambda arg:expression, list) : lambda 함수를 리스트 원소에 적용하기


리스트의 여러개의 각 원소에 lambda 함수를 적용하고 싶으면 map() 함수를 lambda 와 같이 사용하면 됩니다.  (리스트에 문자열이나 튜플과 같은 순서열 자료형이 들어가도 동일함)


만약 리스트에 lambda 함수를 그냥 적용하면 아래처럼 TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int' 처럼 TypeError 가 납니다. 



In [5]: my_list = [1, 2, 3, 4]


In [6]: my_pow2(my_list) # TypeError

Traceback (most recent call last):


File "<ipython-input-6-0c500bc490e4>", line 1, in <module>

my_pow2(my_list) # TypeError


File "<ipython-input-3-6e25a06562c4>", line 1, in <lambda>

my_pow2 = lambda x: x**2


TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'int'

 



아래는 숫자를 제곱해주는 lambda 함수를 map() 함수를 사용하여 리스트의 각 원소에 적용하고, 이 결과값을 리스트(list)로 반환하도록 한 예제입니다. Python3 에서는 map(lambda ) 를 실행하면 리스트가 아니라 map 객체로 반환이 되며, 리스트로 반환을 받고 싶으면 list() 로 명시적으로 변환을 해주어야 합니다. 



In [5]: my_list = [1, 2, 3, 4]


In [7]: list(map(lambda i: i**2, my_list))

Out[7]: [1, 4, 9, 16]

 




  (3) filter(lambda arg: expression, list) : lambda 함수로 리스트의 원소 필터링 하기


다음 예제는 filter(lambda ) 를 사용하여 여러개의 숫자를 원소로 가지는 리스트에서 '짝수(even number)'만을 선별(filter) 하여 리스트로 반환하는 lambda 익명함수 예제입니다. 



In [8]: num_list = range(10)


In [9]: even_list = list(filter(lambda x: (x%2 == 0), num_list))


In [10]: even_list

Out[10]: [0, 2, 4, 6, 8]

 



위의 예제를 리스트 축약(List Comprehension) 으로도 똑같은 결과 값을 구현할 수 있습니다. 메모리 절약 측면에서는 lambda 익명함수가 더 낫고, 코드 가독성 면에서는 리스트 축약이 좀더 나아보입니다. 



In [11]: new_list_2 = [x for x in num_list if x%2 == 0] # list comprehension


In [12]: new_list_2

Out[12]: [0, 2, 4, 6, 8]

 




  (4) reduce(lambda arg: expression, list): 리스트의 원소에 누적으로 함수 적용


reduce 는 lambda 함수를 리스트의 각 원소에 누적으로 계속 적용할 때 사용합니니다. 아래 예제는 reduce(lambda ) 를 사용하여 숫자 1 ~ 4까지 계속 곱하여 1*2*3*4 의 값을 구한 것입니다(4! 을 구한 것임). 



In [13]: from functools import reduce # python3


In [14]: my_list = [1, 2, 3, 4]


In [15]: reduce(lambda x, y: x*y, my_list)

 




  (5) apply(lambda x: pd.Series({'key': function(x)}) 

     : lambda 함수 적용한 칼럼들로 Pandas DataFrame 만들기


마지막으로, 아래는 DataFrame에 카테고리 변수를 기준으로 groupby() 를 하여 apply(lambda ) 함수로 DataFrame 내 각 칼럼별 요약 집계를 한 결과를 가지고 새로운 DataFrame을 만들어보는 예제입니다. 



데이터 전처리, 집계할 때 알아두면 유용합니다. 



In [16]: import pandas as pd


In [17]: aa = pd.DataFrame({'id': ['a', 'a', 'a', 'b', 'b'],

                                     'val': [1, 2, 3, 4, 5]})

In [18]: aa

Out[18]:

  id  val

0  a    1

1  a    2

2  a    3

3  b    4

4  b    5


In [19]: df = aa.groupby('id').apply(lambda x:

                 pd.Series({'clst_obs_cnt': len(x)

                               , 'clst_val_sum': sum(x.val)

                               , 'id_list': x.id.tolist()})).reset_index()


In [20]: df

Out[20]:

  id  clst_obs_cnt  clst_val_sum    id_list

0  a             3             6        [a, a, a]

1  b             2             9        [b, b]




많은 도움이 되었기를 바랍니다. 

Posted by R Friend R_Friend

댓글을 달아 주세요

이번 포스팅에서는 함수의 호출자(caller)에게 코드를 실행시킨 후의 값(result)을 반환해주는 return 문에 대해서 3가지 유형으로 나누어서 소개하겠습니다. 


(1) return + result => 호출자에게 result 반환

(2) no return & no result => code_block 실행 후 종료 (None 반환)

(3) return (no result) => 함수 즉시 종료




첫번째의 return + result 문은 함수를 사용할 때의 일반적인 형태로서 이미 친숙할 것이라고 예상합니다. 두번째와 세번째는 좀 낯설 수도 있는데요, 이번 포스팅에서 예를 들어가면서 자세히 설명해보겠습니다. 



  (1) return + result => 호출자에게 result 값 반환


아래에 my_sum(3, 5) 함수를 호출하여 sum_all = 3 + 5 = 8 의 result 값을 sum_result 에 반환(return)한 예시입니다. 



In [1]: def my_sum(num1, num2):

   ...:     sum_all = num1 + num2

   ...:     return sum_all;


In [2]: sum_result = my_sum(3, 5)


In [3]: sum_result

Out[3]: 8

 




  (2) no return & no result => code_block 실행 후 종료 (None 반환)


다음으로 함수의 마지막 부분에 return 문을 사용하지 않을 경우, 함수 안의 code_block 만 실행할 뿐 호출자에게는 None을 반환합니다 (즉, 아무값도 반환하지 않음). 


이때 함수를 실행한 후의 결과값을 저장한 객체는 "None Type"이 됩니다. 



In [4]: def my_sum2(num1, num2):

   ...:     sum_all = num1 + num2;


In [5]: sum_result2 = my_sum2(3, 5)


In [6]: sum_result2


In [7]: type(sum_result2) # None

Out[7]: NoneType

 



아래의 예제와 같이 하나의 함수 안에 2개의 return 문을 사용할 수도 있습니다. 하지만 이럴 경우 의도치 않게 실수로 버그를 만들 수도 있으므로 가급적 하나의 return 문을 사용하는 것이 좋습니다. 아래의 예제에서는 argument 로 '0' 값을 받을 경우 return 문이 실행되지 않기 때문에 (의도치않게) None 을 반환하고 있습니다. 



In [8]: def my_abs(num):

   ...:     if num > 0:

   ...:         return num

   ...:     elif num < 0:

   ...:         return (-1)*num;


In [9]: abs_result = my_abs(-1)


In [10]: abs_result

Out[10]: 1


In [11]: abs_result = my_abs(0)


In [12]: abs_result   # no result


In [13]: type(abs_result)   # None

Out[13]: NoneType

 




  (3) return only (no result) => 함수 즉시 종료


마지막으로 return 문만 있고 뒤에 result 가 없는 경우입니다. 이럴 경우에 return 문은 함수 호출자에게 값을 반환(return)하는 의미로 쓰인 것이 아니고 함수를 종료(close)시키는 의미로 쓰였다고 보면 됩니다.  


아래의 예에서는 code block에 i를 loop 돌면서 프린트하는 실행문이 들어있으며, 만약 i 가 1부터 하나씩 증가하다가 3이 되면 return 문을 맞닥드려서 함수를 종료시켜버리는 함수입니다.  따라서 my_print(10) 을 실행시켰을 때 1, 2, 3 까지만 프린트가 실행이 되고 거기서 중단이 되었기 때문에 나머지 4 ~ 10까지는 프린트가 안되었습니다. 



In [14]: def my_print(num):

    ...:     for i in range(1, num+1):

    ...:         print(i)

    ...:         if i == 3:

    ...:             return;


In [15]: my_print(3)

1

2

3


In [16]: my_print(10)

1

2

3

 


많은 도움이 되었기를 바랍니다. 


Posted by R Friend R_Friend

댓글을 달아 주세요

지난번 포스팅에서는 함수의 매개변수 중에서 매개변수의 수가 함수 정의 시에 정한 개수로 고정되어 있는 위치 매개변수, 키워드 매개변수, 기본값 매개변수에 대해서 소개하였습니다. 


이번 포스팅에서는 매개변수의 수가 상황에 따라서 변화하는 가변 매개변수 (Arbitrary Arguments, Variable Length Arguments)에 대해서 알아보겠습니다. 


가변 매개변수는 

  - (1) *args_tuple : Positional 매개변수 (Tuple)

  - (2) **args_dict : 키워드 매개변수 (Dictionary)

의 두가지가 있습니다. 




함수 중에 보면 매개변수로 * (Asterisk), ** (Two Asterisks) 가 들어있는 경우 처음보는 분이라면 이게 무슨 뜻인가하고 궁금하였을 것입니다. 이번 포스팅을 보고 나면 이해가 될 것이예요. 



먼저 지난번 포스팅에서 소개했던 위치 매개변수를 복습해보겠습니다. line 2 에서 'print_list' 함수를 정의할 때 매개변수 'text_list' 1개만을 정의했으며, line 3에서 print_list() 함수를 호출할 때 mylist 1개를 매개변수 위치에 입력해주었더니 정상적으로 잘 출력을 해주었습니다. 



In [1]: mylist = ['Korea', 'Sweden', 'Mexico', 'Germany']


In [2]: def print_list(text_list):

    ...: for text in text_list:

    ...: print text


In [3]: print_list(mylist)

Korea

Sweden

Mexico

Germany

 



하지만, 아래의 line 4 에서 처럼 print_list() 함수의 매개변수에 ('Korea', 'Sweden', 'Mexico', 'Germany') 의 4개의 값을 입력하자 'TypeError: print_list() takes exactly 1 arguments(4 given)' 이라는 에러 메시지가 떴습니다. 이처럼 매개변수 값으로 여러개의 값을 이용하고자 할 때 쓰는 것이 가변 매개변수(arbitrary arguments, variable length arguments) 입니다. 



# TypeError: print_list() takes exactly 1 argument (4 given)

In [4]: print_list('Korea', 'Sweden', 'Mexico', 'Germany')

Traceback (most recent call last):


File "<ipython-input-4-5358764707f0>", line 1, in <module>

print_list('Korea', 'Sweden', 'Mexico', 'Germany')


TypeError: print_list() takes exactly 1 argument (4 given)

 


위의 line 4 처럼 했을 때 TypeError 가 났던 것을 Positional 가변 매개변수를 사용하여 정상적으로 작동하도록 고쳐보면 아래와 같습니다. 



  (1) *args_tuple : Positional 매개변수 (Tuple 형태)


괄호 안의 매개변수 입력란에 '* (Asterisk)' 로 시작하는 매개변수 이름을 넣어줍니다. 이 가변 매개변수는 Tuple 형태입니다. 



In [5]: def print_list_2(*text_list):

    ...: for text in text_list:

    ...: print text


In [6]: print_list_2('Korea', 'Sweden', 'Mexico', 'Germany') # more arguments

Korea

Sweden

Mexico

Germany

 



==============================================================


다음으로 사전형(Dictionary Type)을 매개변수 값으로 받아서 프린트를 해주는 함수를 정의해보겠습니다. 



In [7]: worldcup2018 = dict({'A': 'Russia, Saudi, Egypt, Uruguay',

   ...: 'F': 'Korea, Sweden, Mexico, Germany'})


In [8]: def print_group(group):

   ...: for i in group.keys():

   ...: print ("{0} : {1}".format(i, group[i]))


In [9]: print_group(worldcup2018)

A : Russia, Saudi, Egypt, Uruguay

F : Korea, Sweden, Mexico, Germany

 



위의 line 8 에서 정의한 함수에 아래의 line 10 처럼 여러 개의 사전형 값을 매개변수 값으로 입력하면 'TypeError: print_group() got an unexpected keyword argument 'A'' 라는 에러 메시지가 뜹니다. 



# TypeError: print_group() got an unexpected keyword argument 'A'

In [10]: print_group(A='Russia, Saudi, Egypt, Uruguay',

    ...: F='Korea, Sweden, Mexico, Germany')

Traceback (most recent call last):


File "<ipython-input-10-bae24f97b031>", line 2, in <module>

F='Korea, Sweden, Mexico, Germany')


TypeError: print_group() got an unexpected keyword argument 'A'

 



위의 line 10 처럼 매개변수 값으로 다수 개의 사전형 값을 사용하고 싶을 때 **agrs_dict 의 가변형 매개변수를 사용하면 됩니다. 


  (2) **agrs_dict : 키워드 매개변수 (Dictionary 형태)


사전형(Dictionary) 의 Key 값이 키워드 매개변수의 키워드(Keyword) 가 됩니다. 파이썬 라이브러리의 함수들을 보다 보면 **kwagrs 라고 표현된 경우가 있는데요, 이때 kw 가 KeyWord 의 K(ey)W(ord) 의 kw 를 따온 거예요. 



In [11]: def print_group_2(**group):

    ...: for i in group.keys():

    ...: print ("{0} : {1}".format(i, group[i]))


In [12]: print_group_2(A='Russia, Saudi, Egypt, Uruguay',

    ...: F='Korea, Sweden, Mexico, Germany')

A : Russia, Saudi, Egypt, Uruguay

F : Korea, Sweden, Mexico, Germany

 




  (3) 순서 : *args_tuple 먼저, **args_dict 나중에


*args_tuple 과 **args_dict 두 가지 유형의 가변 매개변수를 모두 사용하여 함수를 정의할 수 있습니다. 단, 이때 순서가 중요합니다. *args_tuple 을 먼저 정의하고, **args_dict 를 나중에 이어서 정의해야 합니다. 



#%% arguments sequence matters

In [13]: def print_all(*tup, **dic):

    ...: print(tup)

    ...: print(dic)


In [14]: print_all(1, 2, 3,

    ...: A='Russia, Saudi',

    ...: F='Korea, Sweden')

(1, 2, 3)

{'A': 'Russia, Saudi', 'F': 'Korea, Sweden'}

 



만약 아래의 line 15 처럼 **args_dict 먼저 정의하고, *args_tuple 을 그 뒤에 이어서 정의하게 되면 'SyntaxError: invalid syntax' 라는 에러 메시지가 뜹니다. 



# SyntaxError: invalid syntax

In [15]: def print_all(**dic, *tup):

    ...: print(tup)

    ...: print(dic)

    ...:

    ...:

File "<ipython-input-15-3e33a9bb0436>", line 1

def print_all(**dic, *tup):

^

SyntaxError: invalid syntax

 



많은 도움이 되었기를 바랍니다. 


Posted by R Friend R_Friend

댓글을 달아 주세요

지난번 포스팅에서는 파이썬의 사용자 정의 함수를 사용하면 좋은 점, 함수를 정의하고 호출하는 기본 문법과 예제를 다루었습니다. 


이번 포스팅에서는 파이썬 함수의 입력(input) 값을 받아서 함수가 정의된 작업을 할 수 있도록 해주는 매개변수(Arguments)에 대해서 알아보겠습니다. 


함수를 호출하는데 사용하는 파이썬의 매개변수에는 아래의 4가지 유형이 있습니다. 

  • 위치 매개변수 (Positional Arguments)
  • 키워드 매개변수 (Keyword Arguments)
  • 기본값 매개변수 (Default Arguments)
  • 가변 매개변수 (Arbitrary Arguments)




이중에서 위치, 키워드, 기본값 매개변수까지만 이번 포스팅에서 소개하고, 가변 매개변수는 다음번 포스팅에서 소개하겠습니다. 



  위치 매개변수 (Positional Arguments)


위치 매개변수(Positional Arguments)는 함수 내 매개변수의 위치별 순서와 데이터 타입에 맞게 정확하게 입력을 해주어야만 하는 매개변수를 말합니다.  아래에 '2개'의 숫자를 매개변수로 받아서 평균을 계산해주는 my_avg() 라는 함수가 있다고 했을 때, 입력 매개변수로 '1개'의 숫자만을 입력받게 되었을 때 'TypeError: my_avg() takes exactly 2 arguments (1 given)' 이라는 에러 메시시가 떴습니다. 



In [1]: def my_avg(x1, x2):

   ...: avg_val = (x1 + x2)/ 2

   ...: return avg_val


In [2]: my_avg(2, 4)

Out[2]: 3


In [3]: my_avg(2) # TypeError

Traceback (most recent call last):


File "<ipython-input-3-69b7a0a22718>", line 1, in <module>

my_avg(2)


TypeError: my_avg() takes exactly 2 arguments (1 given)

 




  키워드 매개변수 (Keyword Arguments)


키워드 매개변수는 함수 호출과 관련이 있는데요, 키워드 매개변수를 이용하여 프로그래머는 함수를 호출할 때 매개변수의 이름(parameter name)으로 매개변수를 지정합니다. 


키워드 매개변수를 이용하면 함수를 정의할 때 썼던 매개변수의 입력 순서를 바꾸어서 함수를 호출할 수도 있으며, 코드 가독성도 높아지는 좋은 점이 있습니다. 


아래에 회사명(company)과 임직원 이름(name)을 출력하는 함수로 예를 들어보았습니다. 두번째 호출 예시에서 매개변수 순서를 바꾸어서 입력했음에도 불구하고 출력은 함수에서 정의했던 순서대로 출력되었음을 알 수 있습니다. 



# Keyword Arguments : The caller identifies the arguments by the parameter name

In [4]: def print_me(company, name):

   ...: print("Company : ", company)

   ...: print("Name : ", name)


In [5]: print_me(company="ABCD Co.", name="Mr.Jack")

('Company : ', 'ABCD Co.')

('Name : ', 'Mr.Jack')


# The order of parameters does not matter

In [6]: print_me(name="Mr.Jack", company="ABC Co.")

('Company : ', 'ABC Co.')

('Name : ', 'Mr.Jack')

 



만약 키워드 매개변수를 이용하지 않는 다면 입력 순서와 데이터 타입을 꼭 함수에서 정의한 순서와 맞추어 주어야 합니다. 아래의 2번째 예에서 보면 함수를 호출할 때 매개변수의 입력 순서가 바뀌면 함수를 정의할 때와의 의도와는 다르게 엉뚱한 순서로 값이 출력되었습니다. 



In [7]: print_me("ABCD Co.", "Mr.Jack")

('Company : ', 'ABCD Co.')

('Name : ', 'Mr.Jack')


# Without parameter name, the order matters

In [8]: print_me("Mr.Jack", "ABCD Co.")

('Company : ', 'Mr.Jack')

('Name : ', 'ABCD Co.')

 




  기본값 매개변수 (Default Arguments)


기본값 매개변수는 함수를 호출할 때 매개변수 입력이 없을 경우에 함수를 정의할 때 입력한 기본값(default value)을 사용할 수 있게 해줍니다.  함수를 정의할 때 기본값 설정이 안되어 있는 상태에서 함수 호출 시 매개변수 값 입력을 빼먹으면 TypeError가 나는데요, 기본값 매개변수를 사용하면 TypeError 없이 사용할 수 있게 됩니다. 대신, 기본값 설정을 잘 지정해주어야 겠지요. 


아래의 예에서는 name 매개변수에 "Who?"라는 기본값(default value)을 지정해서 함수를 print_me2 라는 함수를 정의를 했구요, 함수 호출 시 name 매개변수 값을 입력하지 않았더니 => 기본값이 "Who?"가 출력되었네요. 



# Default Argument Value

In [9]: def print_me2(company, name="Who?"):

   ...: print("Company : ", company)

   ...: print("Name : ", name)


In [10]: print_me2(company="ABC Co.") # No TypeError

('Company : ', 'ABC Co.')

('Name : ', 'Who?')

 



단, 기본값 매개변수는 매개변수의 첫번째에는 사용할 수 없습니다. 만약 첫번째 매개변수에 기본값을 지정하려고 하면 아래처럼 'SyntaxError: non-default argument follows default argument)' 라는 에러가 발생합니다. 



# SyntaxError: non-default argument follows default argument

In [11]: def print_me2(company="ABCD Co.", name):

    ...: print("Company : ", company)

    ...: print("Name : ", name)

    ...:

    ...:

File "<ipython-input-11-c9e7590bf632>", line 1

def print_me2(company="ABCD Co.", name):

SyntaxError: non-default argument follows default argument

 



마지막으로, 매개변수는 숫자로 시작할 수 없습니다. 아래처럼 '3_company' 처럼 숫자 '3'으로 매개변수 이름을 시작했더니 'SyntaxError: invalid syntax'라는 에러가 떴습니다. 



In [12]: def print_me3(3_company, name):

    ...: print("Company : ", company)

    ...: print("Name : ", name)

    ...:

    ...:

File "<ipython-input-12-46388f3578d8>", line 1

def print_me3(3_company, name):

^

SyntaxError: invalid syntax

 



다음번 포스팅에서는 가변 매개변수(arbitrary arguments)에 알아보겠습니다. 


많은 도움이 되었기를 바랍니다. 


Posted by R Friend R_Friend

댓글을 달아 주세요

함수(function)는 input을 받아서 특정 과업(들)을 수행하여 output을 반환하도록 짜여진, 잘 조직되고 재사용이 가능한 코드 블록을 말합니다.

 

그동안 파이썬의 내장형 함수(Built-in function), 여러 라이브러리의 함수에 대해서 소개를 했었는데요, 이번 포스팅부터는 사용자가 직접 함수를 정의해서 사용할 수 있는 '사용자 정의 함수 (User-Defined Function, UDF)' 에 대해서 소개하겠습니다.

 

[ 사용자 정의 함수의 유용성 ]

* 사용자 정의 함수를 재사용(reusable)할 수 있습니다.
* 코드를 구조화, 모듈화(modularization) 함으로써 관리하기 쉽습니다.
* 사용자 정의 함수를 사용하여 코드를 간결하게 하고 가독성을 높일 수 있습니다.
* 사용자 정의 함수를 분산해서 개별적으로 작성할 수 있으므로 애플리케이션 개발 속도를 높일 수 있습니다.


사용자 정의 함수는 (1) 사용자 정의 함수의 정의 (Definition), (2) 호출 (Call), (3) 반환 (Return) 의 절차를 따라서 이용할 수 있습니다.

 

 

사용자 정의함수를 정의(define) 할 때는

  • 첫 줄에는 def 로 시작하며
  • 사용자 정의 함수 이름을 쓰고,
  • 괄호 안에는 매개변수 목록을 쓰며,
  • 콜론(:)을 써줍니다.
  • 다음줄 부터는 들여쓰기(indentation)을 꼭 해주어야 하며,
  • 따옴표 세개("""함수 설명""")로 함수에 대한 부가 설명(Docstring)을 넣어주고 (optional)
  • 실행하고자 함는 작업에 대해서 코드블록을 작성합니다.
  • 마지막에 return 뒤에 반환하고자 하는 결과값을 써주면 됩니다.
  • 반환할 값이 없으면 return 은 생략 가능합니다.

 

(1) 숫자를 input으로 받아서 평균을 반환하는 간단한 사용자 정의 함수를 정의(define)해보겠습니다.

 

 

def my_avg(x1, x2):

    avg_val = (float(x1) + float(x2))/2

   

    return avg_val

 

 

 

(2) 위에서 만든 my_avg() 라는 사용자 정의 함수를 호출(call)하여 (2, 3), (2, 4) 의 두 쌍의 숫자들의 평균을 반환(return) 해보겠습니다.

 

 

In [2]: avg_val = my_avg(2, 3)


In [3]: avg_val

Out[3]: 2.5

 

In [4]: my_avg(2, 4)

Out[4]: 3.0

 

 

 

큰 따옴표 세개(""" Docstring """)로 사용자 정의 함수를 설명하는 Docstring을 추가하고, ?함수이름으로 Docstring을 불러와서 참고해보겠습니다.

 

 

def my_avg(x1, x2):

    """

    This function calculates average value of two numbers

    x1: first input number

    x2: second input number

    """

    avg_val = (float(x1) + float(x2))/2

 

    return avg_val


 

In [6]: ?my_avg()

Signature: my_avg(x1, x2)

Docstring:

This function calculates average value of two numbers

x1: first input number

x2: second input number

File: c:\users\admin\<ipython-input-5-d14cc1c6028b>

Type: function

 

 

 

사용자 정의 함수의 코드 블록에 if ~ else 조건문을 추가하여 좀더 복잡한 작업을 할 수도 있습니다. 위의 두 숫자를 input으로 받아서 평균을 반환하는 사용자 정의 함수에다가 '정수(integer) 혹은 부동소수형(float)'이 아니면 "This is not a number" 라는 메시지를 반환하도록 하는 조건문 코드를 추가해보겠습니다.

 

사용자정의함수와 조건문을 같이 쓰므로 콜론(:)으로 코드블록이 시작됨을 알려주고 들여쓰기(indentation)에 주의를 기울여야 합니다.

 

 

def my_avg(x1, x2):

    """

    This function calculates average value of two numbers

    x1: first input number

    x2: second input number

    """

    

    if isinstance(x1, (int, float)) and isinstance(x2, (int, float)):

        avg_val = (float(x1) + float(x2))/2

        return avg_val

    else:

        print("This is not a number")

      


In [8]: my_avg(2, 5)

Out[8]: 3.5


In [9]: my_avg('2', 5)

This is not a number

 

 

많은 도움이 되었기를 바랍니다.

 

Posted by R Friend R_Friend

댓글을 달아 주세요

이번 포스팅에서는 Python NumPy 배열을 여러개의 하위 배열로 분할하는 방법을 소개하겠습니다. 


  • 한 개의 배열을 수평 축(열 방향, column-wise)으로 여러 개의 하위 배열로 분할하기
    - np.hsplit(x, 3), np.hsplit(x, (2, 4))
    - np.split(x, 3, axis=1), np.split(x, (2, 4), axis=1)
  • 한 개의 배열을 수직 축( 방향, row-wise)으로 여러 개의 하위 배열로 분할하기
    - np.vsplit(x, 3), np.vsplit(x, (1, 2))
    - np.split(x, 3, axis=0), np.split(x, (1, 2), axis=0)


[ Python NumPy 배열 분할하기 ]




간단한 예를 들어서 설명하겠습니다. 


 (1) 한 개의 배열을 수평 축(열 방향, column-wise)으로 여러 개의 하위 배열로 분할하기



In [1]: import numpy as np


In [2]: x = np.arange(18).reshape(3, 6)


In [3]: x

Out[3]:

array([[ 0, 1, 2, 3, 4, 5],

        [ 6, 7, 8, 9, 10, 11],

        [12, 13, 14, 15, 16, 17]])



아래의 4가지 함수 모두 동일한 결과를 반환합니다. 

  • np.hsplit(x, 3) : x 배열을 수평 축(열 방향, column-wise)으로 3개의 배열로 분할
  • np.hsplit(x, (2, 4)) : x 배열을 수평 축(열 방향, colomn-wise)의 x[:,0:2], x[:,2:4], x[:,4:6] 위치의 원소를 가지는 3개의 배열로 분할

 np.hsplit(x, 3)

np.hsplit(x, (2, 4)) 


 In [4]: np.hsplit(x, 3)

Out[4]:

[array([[ 0, 1],

         [ 6, 7],

         [12, 13]]), 

 array([[ 2, 3],

         [ 8, 9],

         [14, 15]]), 

 array([[ 4, 5],

         [10, 11],

         [16, 17]])]


 In [5]: np.hsplit(x, (2, 4))

Out[5]:

[array([[ 0, 1],

         [ 6, 7],

         [12, 13]]), 

 array([[ 2, 3],

         [ 8, 9],

         [14, 15]]), 

 array([[ 4, 5],

         [10, 11],

         [16, 17]])]


  • np.split(x, 3, axis=1) = np.hsplit(x, 3) 와 동일
  • np.split(x, (2, 4), axis=1) = np.hsplit(x, (2, 4)) 와 동일

np.split(x, 3, axis=1)

np.split(x, (2, 4), axis=1)

 

In [6]: np.split(x, 3, axis=1)

Out[6]:

[array([[ 0, 1],

         [ 6, 7],

         [12, 13]]), 

 array([[ 2, 3],

         [ 8, 9],

         [14, 15]]), 

 array([[ 4, 5],

         [10, 11],

         [16, 17]])]


 

In [7]: np.split(x, (2, 4), axis=1)

Out[7]:

[array([[ 0, 1],

         [ 6, 7],

         [12, 13]]), 

 array([[ 2, 3],

         [ 8, 9],

         [14, 15]]), 

 array([[ 4, 5],

         [10, 11],

         [16, 17]])]




아래 처럼 하나의 배열을 3개로 분할했을 때, 각 하위 배열을 x1, x2, x3 에 할당할 수 있습니다. 


In [8]: x1, x2, x3 = np.hsplit(x, 3)


In [9]: x1

Out[9]:

array([[ 0, 1],

        [ 6, 7],

        [12, 13]])


In [10]: x2

Out[10]:

array([[ 2, 3],

        [ 8, 9],

        [14, 15]])


In [11]: x3

Out[11]:

array([[ 4, 5],

        [10, 11],

        [16, 17]])

 




(2) 한 개의 배열을 수직 축( 방향, row-wise)으로 여러 개의 하위 배열로 분할하기


 

In [2]: x = np.arange(18).reshape(3, 6)


In [3]: x

Out[3]:

array([[ 0, 1, 2, 3, 4, 5],

        [ 6, 7, 8, 9, 10, 11],

        [12, 13, 14, 15, 16, 17]])



  • np.vsplit(x, 3) : x배열을 수직 축 (행 방향, row-wise) 으로 3개의 하위 배열로 분할하기
  • np.vsplit(x, (1, 2)) : x배열을 수직 축 (행 방향, row-wise) 기준으로 x[0:1, :], x[1:2, :], x[2:3, :] 위치의 원소를 가지는 3개의 하위 배열로 분할하기

np.vsplit(x, 3

np.vsplit(x, (1, 2))

 

In [12]: np.vsplit(x, 3)

Out[12]:

[array([[0, 1, 2, 3, 4, 5]]),

 array([[ 6, 7, 8, 9, 10, 11]]),

 array([[12, 13, 14, 15, 16, 17]])]



 In [13]: np.vsplit(x, (1, 2))

Out[13]:

[array([[0, 1, 2, 3, 4, 5]]),

 array([[ 6, 7, 8, 9, 10, 11]]),

 array([[12, 13, 14, 15, 16, 17]])]



  • np.split(x, 3, axis=0) = np.vsplit(x, 3) 과 동일
  • np.split(x, (1, 2), axis=0) = np.vsplit(x, (1, 2)) 와 동일

np.split(x, 3, axis=0)

np.split(x, (1, 2), axis=0) 

 

In [14]: np.split(x, 3, axis=0)

Out[14]:

[array([[0, 1, 2, 3, 4, 5]]),

 array([[ 6, 7, 8, 9, 10, 11]]),

 array([[12, 13, 14, 15, 16, 17]])]


 

In [15]: np.split(x, (1, 2), axis=0)

Out[15]:

[array([[0, 1, 2, 3, 4, 5]]),

 array([[ 6, 7, 8, 9, 10, 11]]),

 array([[12, 13, 14, 15, 16, 17]])]




저는 np.hsplit()과 np.vsplit() 이 행과 열 중에서 어디를 기준으로 분할이 되는 건지 자꾸 헷갈리네요. 직관적인 코드 가독성면에서는 np.split(x, n, axis=0), np.split(x, n, axis=1) 처럼 axis = 0 or 1 로 표기해주는 방식이 저한테는 더 이해하기가 쉽네요. 


많은 도움이 되었기를 바랍니다. 


Posted by R Friend R_Friend

댓글을 달아 주세요

이번 포스팅에서는 Python NumPy 배열(array) 데이터를 외부 파일로 저장(save)하는 방법, 외부 파일을 배열로 불러오는(load) 방법에 대해서 알아보겠습니다.


  • np.save() : 1개의 배열을 NumPy format의 바이너리 파일로 저장하기 (Save a single array to a binary file in NumPy format)
  • np.load() : np.save()로 저장된 *.npy 파일을 배열로 불러오기 (Open a *.npy file and load it as an array)
  • np.savez() : 여러개의 배열을 1개의 압축되지 않은 *.npz 포맷 파일로 저장하기 (Save several arrays into a single file in uncompressed .npz format)
  • np.load() : np.savez()로 저장된 *.npz 파일을 배열로 불러오기 (Open a *.npz file and load it as an array)
  • np.save_compressed() : 여러개의 배열을 1개의 압축된 *.npz 포맷 파일로 저장하기 (Save several arrays into a single file in compressed .npz format)
  • np.load() : np.save_compressed()로 저장된 압축된 *.npz 파일을 배열러 불러오기 (Open a compressed *.npz file and load it as an array)
  • np.savetext(: 여러개의 배열을 텍스트 파일로 저장하기 (Save several array to a file as plain text)
  • np.loadtext(: 텍스트 파일을 배열로 불러오기 (Open a text file and load it as an array)


[ Python NumPy 배열을 파일로 저장하기(save), 불러오기(load) ]




하나씩 간단한 예를 들어서 설명하겠습니다. 


 > np.save() : 1개의 배열을 NumPy format의 바이너리 파일로 저장하기

 > np.load() : np.save()로 저장된 *.npy 파일을 배열로 불러오기 



In [1]: import numpy as np


In [2]: x = np.array([0, 1, 2, 3, 4])


# 배열을 저장하기

In [3]: np.save('D:/admin/Documents/x_save', x) # x_save.npy


[ .npy 형식으로 저장된 파일 ]


# 배열로 불러오기

In [4]: x_save_load = np.load('D:/admin/Documents/x_save.npy')


In [5]: x_save_load

Out[5]: array([0, 1, 2, 3, 4])

 




 > np.savez() : 여러개의 배열을 1개의 압축되지 않은 *.npz 포맷 파일로 저장하기

 > np.load() : np.savez()로 저장된 *.npz 파일을 배열로 불러오기



In [6]: x = np.array([0, 1, 2, 3, 4])


In [7]: y = np.array([5, 6, 7, 8, 9])


In [8]: np.savez('D:/admin/Documents/xy_savez'

   ...: , x=x, y=y) # 각 배열에 이름 부여

 

 [ .npz 형식으로 저장된 파일 ]



np.load() 함수로 .npz 파일을 열어서 배열로 불러올 수 있습니다. 이때 불러온 파일의 type은 'numpy.lib.npyio.NpzFile' 이며, 개별 배열을 indexing 하려면 [ ]  를 사용합니다. 


# 배열로 불러오기

In [9]: xy_savez_load = np.load('D:/admin/Documents/xy_savez.npz')


In [10]: type(xy_savez_load)

Out[10]: numpy.lib.npyio.NpzFile


In [11]: xy_savez_load['x']

Out[11]: array([0, 1, 2, 3, 4])


In [12]: xy_savez_load['y']

Out[12]: array([5, 6, 7, 8, 9])

 


np.load() 함수로 연 파일을 더이상 사용할 일이 없으면 메모리 효율 관리를 위해 file.close() 로 닫아주어야 합니다. .close() 로 파일을 닫은 상태에서 indexing 을 하려면 'NoneType' object has no attribute 'open' 에러가 납니다. 


In [13]: xy_savez_load.close()


In [14]: xy_savez_load['x'] # AttributeError: 'NoneType' object has no attribute 'open'

Traceback (most recent call last):


File "<ipython-input-14-14d248a305d2>", line 1, in <module>

xy_savez_load['x'] # AttributeError: 'NoneType' object has no attribute 'open'


File "C:\Users\admin\Anaconda3\envs\py_v36\lib\site-packages\numpy\lib\npyio.py", line 226, in __getitem__

bytes = self.zip.open(key)


AttributeError: 'NoneType' object has no attribute 'open'

 




 > np.save_compressed() : 여러개의 배열을 1개의 압축된 *.npz 포맷 파일로 저장하기

 > np.load() : np.save_compressed()로 저장된 압축된 *.npz 파일을 배열러 불러오기



In [15]: x = np.arange([0, 1, 2, 3, 4])


In [16]: y = np.array([5, 6, 7, 8, 9])


In [17]: np.savez_compressed('D:/admin/Documents/xy_savez_compress'

    ...: , x=x, y=y)

 

 [ .npz 형식으로 압축되어 저장된 파일 ]



np.load() 함수로 불러오기를 하면 'numpy.lib.npyio.NpzFile' type 이며, [ ] 를 사용해서 배열을 indexing 할 수 있습니다. 사용을 끝냈으면 .close() 함수로 닫아줍니다. 


In [18]: xy_savez_compress_load = np.load('D:/admin/Documents/xy_savez_compress.npz')


In [19]: type(xy_savez_compress_load)

Out[19]: numpy.lib.npyio.NpzFile


In [20]: xy_savez_compress_load['x']

Out[20]: array([0, 1, 2, 3, 4])


In [21]: xy_savez_compress_load['y']

Out[21]: array([5, 6, 7, 8, 9])


In [22]: xy_savez_compress_load.close()

 




 > np.savetext() : 여러개의 배열을 텍스트 파일로 저장하기

 > np.loadtext() : 텍스트 파일을 배열로 불러오기


header, footer 로 '#'으로 시작되는 부가설명을 추가할 수 있습니다. 

fmt 로 포맷을 지정할 수 있습니다. 아래 예에서는 소수점 2자리까지만 고정된 자리수로 표현하도록 해보았습니다. 


In [23]: x = np.array([0, 1, 2, 3, 4])


In [24]: y = np.array([5, 6, 7, 8, 9])


In [25]: np.savetxt('D:/admin/Documents/xy_savetxt.txt'

   ...: , (x, y) # x,y equal sized 1D arrays

   ...: , header='--xy save start--'

   ...: , footer='--xy save end--'

   ...: , fmt='%1.2f') # the second digit after the decimal point

 

 [ Text file 로 저장된 배열 ]



np.loadtxt() 함수로 텍스트 파일을 배열로 불러올 수 있으며, ndarray type 으로 바로 불러오게 됩니다. 


In [26]: xy_savetxt_load = np.loadtxt('D:/admin/Documents/xy_savetxt.txt')


In [27]: xy_savetxt_load

Out[27]:

array([[ 0., 1., 2., 3., 4.],

        [ 5., 6., 7., 8., 9.]])

 

In [28]: type(xy_savetxt_load)

Out[28]: numpy.ndarray




2D array 도 텍스트 파일로 저장할 수 있습니다. 

 

In [29]: x2 = np.arange(12).reshape(3, 4)


In [30]: x2

Out[30]:

array([[ 0, 1, 2, 3],

        [ 4, 5, 6, 7],

        [ 8, 9, 10, 11]])


In [31]: np.savetxt('D:/admin/Documents/x2_savetxt.txt'

    ...: , x2

    ...: , fmt='%1.2f')


 [ Text 파일로 저장된 2D 배열 ]



np.loadtxt() 함수로 텍스트 파일을 배열로 불러올 수 있습니다. 원래의 x2 배열과 정확하게 동일하게 잘 불러왔습니다. 


In [32]: x2_savetxt_load = np.loadtxt('D:/admin/Documents/x2_savetxt.txt')


In [33]: x2_savetxt_load

Out[33]:

array([[ 0., 1., 2., 3.],

        [ 4., 5., 6., 7.],

        [ 8., 9., 10., 11.]])

 


많은 도움이 되었기를 바랍니다. 


Posted by R Friend R_Friend

댓글을 달아 주세요

이번 포스팅에서는 Python numpy 배열을 정렬(array sorting)하는 방법에 대해서 소개하겠습니다.

 

- (1) 1차원 배열 정렬 : np.sort(x)

- (2) 1차원 배열 거꾸로 정렬 : np.sort(x)[::-1] , x[np.argsort(-x)]

- (3) 2차원 배열 열 축 기준으로 정렬 : np.sort(x, axis=1)

- (4) 2차원 배열 행 축 기준으로 정렬 : np.sort(x, axis=0)

- (5) 2차원 배열 행 축 기준으로 거꾸로 정렬 : np.sort(x, axis=0)[::-1]

 


[ Python Numpy 배열 정렬: np.sort() ]

 



  (1) 1차원 배열 정렬 : np.sort(x)

 

 

In [1]: import numpy as np


In [2]: x = np.array([4, 2, 6, 5, 1, 3, 0])


In [3]: np.sort(x)

Out[3]: array([0, 1, 2, 3, 4, 5, 6])

 

 

 

참고로, np.sort(x) 메소드는 원래의 배열은 그대로 둔채로 정렬이 된 결과를 복사본으로 반환합니다.

반면에 x.sort() 메소드는 원래의 배열 자체를 정렬합니다.

 

np.sort(x) 

=> 원래 배열은 그래로, 정렬 결과 복사본 반환

x.sort()

=> 배열 자체를 정렬

 

In [2]: x = np.array([4, 2, 6, 5, 1, 3, 0])


In [3]: np.sort(x)

Out[3]: array([0, 1, 2, 3, 4, 5, 6])


In [4]: x

Out[4]: array([4, 2, 6, 5, 1, 3, 0])

 

 In [5]: x = np.array([4, 2, 6, 5, 1, 3, 0])

   ...:


In [6]: x.sort()


In [7]: x

Out[7]: array([0, 1, 2, 3, 4, 5, 6])

 

 

 

 (2) 1차원 배열 거꾸로 정렬 : np.sort(x)[::-1] , x[np.argsort(-x)]

 

배열을 거꾸로 정렬하는 방법에는 2가지가 있습니다.

 

(2-1) np.sort(x)[::-1] : 정렬을 한 후 mirror view 생성

 

 

In [8]: x = np.array([4, 2, 6, 5, 1, 3, 0])


In [9]: x_reverse_1 = np.sort(x)[::-1] # mirror view


In [10]: x_reverse_1

Out[10]: array([6, 5, 4, 3, 2, 1, 0])

 

 

 

(2-2) x[np.argsort(-x)] : np.argsort() 로 index를 받아서 indexing 해오기

 

 

In [11]: x = np.array([4, 2, 6, 5, 1, 3, 0])


In [12]: x_reverse_2 = x[np.argsort(-x)] # copy of reversed sorting


In [13]: x_reverse_2

Out[13]: array([6, 5, 4, 3, 2, 1, 0])

 

 



(3) 2차원 배열 열 축 기준으로 정렬 (from left to right) : np.sort(x, axis=1)


'axis = 1' 옵션을 주면 열 축을 기준으로, 좌에서 우로 (from left to right) 정렬을 합니다. 

이게 좀 헷갈릴 수 있는데요, 아래 예제로 확인해 보시기 바랍니다. 



In [14]: x2 = np.array([[2, 1, 6],

    ...:                       [0, 7, 4],

    ...:                       [5, 3, 2]])


In [15]: x2_sort_axis_1 = np.sort(x2, axis=1) # default


In [16]: x2_sort_axis_1

Out[16]:

array([[1, 2, 6],

        [0, 4, 7],

        [2, 3, 5]])

 




 (4) 2차원 배열 행 축 기준으로 정렬 (from top to bottom) : np.sort(x, axis=0)



In [17]: x2 = np.array([[2, 1, 6],

    ...:                       [0, 7, 4],

    ...:                       [5, 3, 2]])


In [18]: x2_sort_axis_0 = np.sort(x2, axis=0)


In [19]: x2_sort_axis_0

Out[19]:

array([[0, 1, 2],

        [2, 3, 4],

        [5, 7, 6]])

 




 (5) 2차원 배열 열 축 기준으로 거꾸로 정렬 (from bottom to top, reversely) 

     : np.sort(x, axis=1)[::-1]



In [20]: x2 = np.array([[2, 1, 6],

    ...:                       [0, 7, 4],

    ...:                       [5, 3, 2]])


In [21]: x2_sort_axis_0_reverse = np.sort(x2, axis=0)[::-1]


In [22]: x2_sort_axis_0_reverse

Out[22]:

array([[5, 7, 6],

        [2, 3, 4],

        [0, 1, 2]])

 


 

참고로 Python

 - (1) DataFrame 정렬 : DataFrame.sort_values()

 - (2) Tuple 정렬 : sorted(tuple, key)

 - (3) List 정렬 : list.sort(), sorted(list)

http://rfriend.tistory.com/281  을 참고하시기 바랍니다.


사전 자료형(Dictionary)의 키, 값 기준 정렬은 https://rfriend.tistory.com/473 를 참고하세요. 


데이터 형태마다 정렬 함수, 메소드가 조금씩 달라서 매번 헷갈리곤 합니다. ㅜ_ㅜ

 

많은 도움 되었기를 바랍니다.

 

Posted by R Friend R_Friend

댓글을 달아 주세요

이번 포스팅에서는 Python numpy 의 메소드, 함수 중에서 


- 최소값, 최대값, 혹은 조건에 해당하는 색인(index) 값을 찾기 

   : np.argmin(), np.argmax(), np.where()


- 최소값, 최대값, 혹은 조건에 맞는 값 찾기 

   : np.min(), np.max(), x[np.where()]


에 대해서 소개하겠습니다. 


분석할 때 꽤 많이 사용되므로 기억해두시면 좋겠습니다. 





  (1) 최소값(min), 최대값(max): np.min(), np.max()


x.min(), np.min(x), min(x) 모두 동일한 결과를 반환합니다. 



In [1]: import numpy as np


In [2]: x = np.array([5, 4, 3, 2, 1, 0])


In [3]: x.min()

Out[3]: 0


In [4]: np.min(x)

Out[4]: 0


In [5]: x.max()

Out[5]: 5


In [6]: np.max(x)

Out[6]: 5

 




  (2) 최소값, 최대값의 색인 위치: np.argmin(), np.argmax()



In [7]: x.argmin()

Out[7]: 5


In [8]: np.argmin(x)

Out[8]: 5


In [9]: x.argmax()

Out[9]: 0


In [10]: np.argmax(x)

Out[10]: 0

 




  (3) 조건에 맞는 값의 색인 위치: np.where()


배열에서 3과 같거나 큰 값을 가지는 색인의 위치를 알고 싶을 때, 


 

In [11]: np.where(x >= 3)

Out[11]: (array([0, 1, 2], dtype=int64),)




(4) 조건에 맞는 값을 indexing 하기: x[np.where()] 


배열에서 3과 같거나 큰 값을 indexing 하고 싶을 때, 



In [12]: x[np.where(x >= 3)]

Out[12]: array([5, 4, 3])

 




  (5) 조건에 맞는 값을 특정 다른 값으로 변환하기

     : np.where(조건, 조건에 맞을 때 값, 조건과 다를 때 값)


배열의 값이 3과 같거나 크면 3으로 변환하고, 3보다 작으면 그대로 값을 유지하고 싶을 때, 

(for loop & if else 조건문을 사용하는 것보다 수십배 빠르므로 매우 유용함)



In [13]: np.where(x >= 3, 3, x)

Out[13]: array([3, 3, 3, 2, 1, 0])

 


 

참고로, 위의 np.where를 사용한 배열 값 변환을 for loop & if else 조건문을 사용해서 써보면 아래와 같습니다. for loop은 데이터 사이즈가 커질 경우 속도가 매우 느려지므로, 위의 대용량 데이터는 벡터화된 연산을 하는 np.where() 함수 사용을 권합니다. .

 

 

In [14]: x_2 = []

    ...: for i in list(x):

    ...: if i >= 3:

    ...: x_2.append(3)

    ...: else:

    ...: x_2.append(i)

    ...:

    ...:


In [15]: x_2 = np.asarray(x_2)


In [16]: type(x_2)

Out[16]: numpy.ndarray


In [17]: x_2

Out[17]: array([3, 3, 3, 2, 1, 0])

 

 

많은 도움이 되었기를 바랍니다. 

 

Posted by R Friend R_Friend

댓글을 달아 주세요

이번 포스팅에서는 Python numpy 의 집합함수(set functions)에 대해서 알아보겠습니다.

 

한 개, 혹은 두 개의 1차원 ndarray 집합에 대해서

 

(1) unique(x) : 배열 내 중복된 원소 제거 후 유일한 원소를 정렬하여 반환
(2) intersect1d(x, y) : 두 개의 배열 x, y 의 교집합을 정렬하여 반환
(3) union1d(x, y) : 두 개의 배열 x, y의 합집합을 정렬하여 반환
(4) in1d(x, y) : 첫번째 배열 x가 두번째 배열 y의 원소를 포함하고 있는지 여부의 불리언 배열을 반환
(5) setdiff1d(x, y) : 첫번째 배열 x로 부터 두번째 배열 y를 뺀 차집합을 반환
(6) setxor1d(x, y) : 두 배열 x, y의 합집합에서 교집합을 뺀 대칭차집합을 반환

 

해주는 다양한 집합함수가 있습니다.

 

[ Python numpy 집합 함수 (set functions) ]

 

 

 

순서대로 예를 들어서 설명하겠습니다.  위의 벤다이어그램을 참고하시기 바랍니다.

 

 (1) np.unique(x) : 배열 내 중복된 원소 제거 후 유일한 원소를 정렬하여 반환

 

 

In [1]: import numpy as np


In [2]: x = np.array([1, 2, 3, 1, 2, 4])


In [3]: np.unique(x)

Out[3]: array([1, 2, 3, 4])

 

 

참고로, pure python의 sorted(set(x)) 와 np.unique(x) 는 동일합니다.

 

In [4]: sorted(set(x))

Out[4]: [1, 2, 3, 4]

 

 

 

 

 

 (2) np.intersect1d(x, y) : 두 개의 배열 x, y 의 교집합을 정렬하여 반환

 

 

In [5]: x = np.array([1, 2, 3, 4])


In [6]: y = np.array([3, 4, 6, 5])


In [7]: np.intersect1d(x, y)

Out[7]: array([3, 4])

 

 

 

 

 (3) np.union1d(x, y) : 두 개의 배열 x, y의 합집합을 정렬하여 반환

 

 

In [8]: x = np.array([1, 2, 3, 4])


In [9]: y = np.array([3, 4, 6, 5])


In [10]: np.union1d(x, y)

Out[10]: array([1, 2, 3, 4, 5, 6])

 

 

 

 

 (4) np.in1d(x, y) : 첫번째 배열이 두번째 배열의 원소를 포함하고 있는지 여부의

                         불리언 배열을 반환

 

 

In [11]: x = np.array([1, 2, 3, 4, 5, 6])


In [12]: y = np.array([2, 4])


In [13]: np.in1d(x, y)

Out[13]: array([False, True, False, True, False, False])

 

 

 

 

 (5) np.setdiff1d(x, y) : 첫번째 배열 x로 부터 두번째 배열 y를 뺀 차집합을 반환

 

 

In [14]: x = np.array([1, 2, 3, 4])


In [15]: y = np.array([3, 4, 5, 6])


In [16]: np.setdiff1d(x, y)

Out[16]: array([1, 2])

 

 

 

 

 (6) np.setxor1d(x, y) : 두 배열 x, y의 합집합에서 교집합을 뺀 대칭차집합을 반환

 

 

In [17]: x = np.array([1, 2, 3, 4])


In [18]: y = np.array([3, 4, 5, 6])


In [19]: np.setxor1d(x, y)

Out[19]: array([1, 2, 5, 6])

 

 

많은 도움이 되었기를 바랍니다.

Posted by R Friend R_Friend

댓글을 달아 주세요