끄적거림

[Pandas] 서로 길이가 다른 list/Series 합쳐서 DataFrame 만들기 in python & R 본문

Python/Data Handling

[Pandas] 서로 길이가 다른 list/Series 합쳐서 DataFrame 만들기 in python & R

Signing 2020. 8. 13. 10:28
728x90
반응형

데이터를 만지다보면 여러 array형 데이터(list/Series in python, vector in R)를 합쳐서 새로운 dataframe 형태로 만들 경우가 생긴다.

 

보통의 경우 길이가 같은 array들을 이어 붙여야 우리가 원하는 딱 맞는 이쁜 데이터프레임 객체가 생성된다.

 

하지만 항상 그럴 경우만 생기지는 않으니, 길이가 서로 다른 1차원 자료형을 붙여 dataframe형태로 만들때를 생각해보자!

 

 


 

 

너무도 당연한 이야기이지만 서로 다른 길이의 1차원 자료형을 붙이면 제일 긴 길이의 데이터를 가지고 데이터프레임 객체가 생성될 것이고, 빈 공간은 NA로써 혹은 Nan 혹은 Null값으로 채워지길 바란다.

 

우선 R이 편하니 R부터 해보자.

 

 

1. R - cbind

다음과 같은 길이가 다른 객체들이 있다.

a <- 1:8
b <- 1:10
c <- letters[1:6]

이들을 모두 합치기 위해서는 처음으로 생각드는 것은 data.frame 객체에 바로 넣는 것이다.

data.frame(A = a, B = b, C = c)
# Error in data.frame(A = a, B = b, C = c) : 
#  arguments imply differing number of rows: 8, 10, 6

하지만 이렇게 하면 에러가 난다.

길이가 다르기 때문에 에러가 난다고 한다.

 

다른 방법으로는 cbind를 두 번 사용하는 것과 do.call 함수를 사용하는 것이다.

# R
# method 1: double cbind
cbind(cbind(a,b), c)

# method 2: do.call function
do.call(cbind, list(a,b,c))

# Same Result
# a   b    c  
# [1,] "1" "1"  "a"
# [2,] "2" "2"  "b"
# [3,] "3" "3"  "c"
# [4,] "4" "4"  "d"
# [5,] "5" "5"  "e"
# [6,] "6" "6"  "f"
# [7,] "7" "7"  "a"
# [8,] "8" "8"  "b"
# [9,] "1" "9"  "c"
# [10,] "2" "10" "d"

이번엔 warning이 뜨면서 결과가 위와 같이 나오긴 한다.

cbind를 두 사용하는 것에서 일단 마음에 안드는 것이 1) cbind 두 번 사용 2) na값이 아닌 다른 값.

 

warning 메세지는 그렇다쳐도 Na값이 아닌 값이 채워지는 것은 왜 그럴까?

 

그 이유는 바로 Recycle Rule이 적용되었기 때문이다.

 

Recycle Rule이란, R이 연산을 진행할 때, 길이가 부족한 데이터를 알아서 채워주는 연산방법이다.

R 자체적으로 내장되어있기 때문에 이 부분에 유의해서 진행해야한다.(이 부분은 나중에 따로 포스팅할 예정)

 

또한 cbind를 두 번 사용하는 것이 다소 좀 거슬린다.

지금은 객체가 3개이기에 두번 사용했지만, 객체가 N개라면 N-1번을 해야할 상황이다.

 

이를 위해 등장한 것이 do.call 함수이다.(이 함수에 대해서도 포스팅 예정)

 

어쨌든 내가 원하던 결과는 이 것이 아니다. 제대로 하려면 다음과 같다.

length(a) <- max(length(a),length(b),length(c))
length(b) <- max(length(a),length(b),length(c))
length(c) <- max(length(a),length(b),length(c))
do.call(cbind, list(a,b,c))

# [,1] [,2] [,3]
# [1,] "1"  "1"  "a" 
# [2,] "2"  "2"  "b" 
# [3,] "3"  "3"  "c" 
# [4,] "4"  "4"  "d" 
# [5,] "5"  "5"  "e" 
# [6,] "6"  "6"  "f" 
# [7,] "7"  "7"  NA  
# [8,] "8"  "8"  NA  
# [9,] NA   "9"  NA  
# [10,] NA   "10" NA 

더 번거로움이 생긴다. 어쨌든 완성은 했다.

 

그럼 이제 파이썬에서는 어떻게 하는지 확인해보자.

 


 

다음과 같이 데이터를 만든다.

a = [i for i in range(6)]
b = [i for i in range(10)]
c = [i for i in range(8)]

그리고 이 객체들을 dictonary로 묶어준다.

dic = {
    'A' : a,
    'B' : b,
    'C' : c
}

# Out[6]: 
# {'A': [0, 1, 2, 3, 4, 5],
#  'B': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
#  'C': [0, 1, 2, 3, 4, 5, 6, 7]}

그리고 아래의 코드대로 진행해주면 된다.

res = pd.DataFrame.from_dict(dic, orient='index')

Out[10]: 
#    0  1  2  3  4  5    6    7    8    9
# A  0  1  2  3  4  5  NaN  NaN  NaN  NaN
# B  0  1  2  3  4  5  6.0  7.0  8.0  9.0
# C  0  1  2  3  4  5  6.0  7.0  NaN  NaN

하지만 원하던 행과 열이 아니기 때문에 이를 바꿔준다.

res = res.transpose()
res

# Out[12]: 
#      A    B    C
# 0  0.0  0.0  0.0
# 1  1.0  1.0  1.0
# 2  2.0  2.0  2.0
# 3  3.0  3.0  3.0
# 4  4.0  4.0  4.0
# 5  5.0  5.0  5.0
# 6  NaN  6.0  6.0
# 7  NaN  7.0  7.0
# 8  NaN  8.0  NaN
# 9  NaN  9.0  NaN

 

 

그럼 해결!

728x90
반응형
Comments