티스토리 뷰

05_columns(한글)

Introduction to DataFrames

Bogumił Kamiński, 2018년 5월 23일

출처

함께보기

In [1]:
using DataFrames # load package

데이터프레임의 열 다루기 (Manipulating columns of DataFrame)

열 이름 다시 붙이기 (Renaming columns)

기본 열 이름을 갖고있는 논리값으로 이루어진 데이터프레임으로 시작해보자.

In [2]:
x = DataFrame(Bool, 3, 4)
Out[2]:
x1x2x3x4
BoolBoolBoolBool
1falsefalsefalsetrue
2falsetruetruetrue
3truefalsefalsetrue

rename을 이용해서, 새로운 DataFrame을 만들 수 있다. 여기서는 :x1:A로 바꿨다. (물론 rename으로 여러 쌍을 바꿀 수도 있다.)

In [3]:
rename(x, :x1 => :A)
Out[3]:
Ax2x3x4
BoolBoolBoolBool
1falsefalsefalsetrue
2falsetruetruetrue
3truefalsefalsetrue

rename!으로 우리는 in place transformation도 할 수 있다.

이번에는 모든 열 이름에 대해서 적용시켜봤다.

In [4]:
rename!(c -> Symbol(string(c)^2), x)
Out[4]:
x1x1x2x2x3x3x4x4
BoolBoolBoolBool
1falsefalsefalsetrue
2falsetruetruetrue
3truefalsefalsetrue

우리는 또한 특정한 열 이름을 몰라도 바꿀 수 있다.

여기서는 3열의 이름을 바꾸고 새로운 데이터프레임을 만들었다.

In [5]:
rename(x, names(x)[3] => :third)
Out[5]:
x1x1x2x2thirdx4x4
BoolBoolBoolBool
1falsefalsefalsetrue
2falsetruetruetrue
3truefalsefalsetrue

names!를 이용해서, 모든 열의 이름을 바꿀 수 있다.

In [6]:
names!(x, [:a, :b, :c, :d])
Out[6]:
abcd
BoolBoolBoolBool
1falsefalsefalsetrue
2falsetruetruetrue
3truefalsefalsetrue

이름을 중복되게 설정하려고 하면 에러난다.

In [7]:
names!(x, fill(:a, 4))
ArgumentError: Duplicate variable names: Symbol[:a, :a, :a, :a].
Pass makeunique=true to make them unique using a suffix automatically.

Stacktrace:
 [1] #names!#3(::Bool, ::Bool, ::Function, ::DataFrames.Index, ::Array{Symbol,1}) at /home/yt/.julia/packages/DataFrames/1PqZ3/src/other/index.jl:34
 [2] #names! at ./none:0 [inlined]
 [3] #names!#15 at /home/yt/.julia/packages/DataFrames/1PqZ3/src/abstractdataframe/abstractdataframe.jl:139 [inlined]
 [4] names!(::DataFrame, ::Array{Symbol,1}) at /home/yt/.julia/packages/DataFrames/1PqZ3/src/abstractdataframe/abstractdataframe.jl:136
 [5] top-level scope at In[7]:1

makeunique=true 를 사용하면, 중복되는 이름도 사용할 수 있게 되지만, 조금 다르게 들어간다.

In [8]:
names!(x, fill(:a, 4), makeunique=true)
Out[8]:
aa_1a_2a_3
BoolBoolBoolBool
1falsefalsefalsetrue
2falsetruetruetrue
3truefalsefalsetrue

열 재배치 (Reordering columns)

우리는 names(x) 벡터를 필요에 따라 재배치 할 수 있다.

In [9]:
using Random
Random.seed!(1234) #srand(1234)
x[shuffle(names(x))]
Out[9]:
a_1a_3a_2a
BoolBoolBoolBool
1falsetruefalsefalse
2truetruetruefalse
3falsetruefalsetrue

또한 permutecols! 를 이용해도 바꿀 수 있다.

In [10]:
permutecols!(x, [2, 1, 3, 4])
Out[10]:
a_1aa_2a_3
BoolBoolBoolBool
1falsefalsefalsetrue
2truefalsetruetrue
3falsetruefalsetrue
In [11]:
permutecols!(x, [:a, :a_1, :a_2, :a_3])
Out[11]:
aa_1a_2a_3
BoolBoolBoolBool
1falsefalsefalsetrue
2falsetruetruetrue
3truefalsefalsetrue

열 추가 혹은 합치기 (Merging/adding columns)

In [12]:
x = DataFrame([(i,j) for i in 1:3, j in 1:4])
Out[12]:
x1x2x3x4
Tuple…Tuple…Tuple…Tuple…
1(1, 1)(1, 2)(1, 3)(1, 4)
2(2, 1)(2, 2)(2, 3)(2, 4)
3(3, 1)(3, 2)(3, 3)(3, 4)

hcat으로, 우리는 두 데이터프레임을 합칠 수 있다. 열 이름이 유일하다면 [x y] 구문을 이용해서도 합칠 수 있다.

In [13]:
hcat(x, x, makeunique=true)
Out[13]:
x1x2x3x4x1_1x2_1x3_1x4_1
Tuple…Tuple…Tuple…Tuple…Tuple…Tuple…Tuple…Tuple…
1(1, 1)(1, 2)(1, 3)(1, 4)(1, 1)(1, 2)(1, 3)(1, 4)
2(2, 1)(2, 2)(2, 3)(2, 4)(2, 1)(2, 2)(2, 3)(2, 4)
3(3, 1)(3, 2)(3, 3)(3, 4)(3, 1)(3, 2)(3, 3)(3, 4)
In [14]:
[x x]
┌ Warning: Duplicate variable names are deprecated: pass makeunique=true to add a suffix automatically.
│   caller = ip:0x0
└ @ Core :-1
Out[14]:
x1x2x3x4x1_1x2_1x3_1x4_1
Tuple…Tuple…Tuple…Tuple…Tuple…Tuple…Tuple…Tuple…
1(1, 1)(1, 2)(1, 3)(1, 4)(1, 1)(1, 2)(1, 3)(1, 4)
2(2, 1)(2, 2)(2, 3)(2, 4)(2, 1)(2, 2)(2, 3)(2, 4)
3(3, 1)(3, 2)(3, 3)(3, 4)(3, 1)(3, 2)(3, 3)(3, 4)

hcat을 이용해서 새로운 열을 추가할 수도 있다. 이 때, 이름은 :x1로 고정되는데, makeunique=true가 필요할 수도 있다.

In [15]:
y = hcat(x, [1,2,3], makeunique=true)
Out[15]:
x1x2x3x4x1_1
Tuple…Tuple…Tuple…Tuple…Int64
1(1, 1)(1, 2)(1, 3)(1, 4)1
2(2, 1)(2, 2)(2, 3)(2, 4)2
3(3, 1)(3, 2)(3, 3)(3, 4)3
In [16]:
[x [1,2,3]]
Out[16]:
x1x2x3x4x1_1
Tuple…Tuple…Tuple…Tuple…Int64
1(1, 1)(1, 2)(1, 3)(1, 4)1
2(2, 1)(2, 2)(2, 3)(2, 4)2
3(3, 1)(3, 2)(3, 3)(3, 4)3

hcat을 이용해서 앞에 붙일 수도 있다.

In [17]:
hcat([1,2,3], x, makeunique=true)
Out[17]:
x1x1_1x2x3x4
Int64Tuple…Tuple…Tuple…Tuple…
11(1, 1)(1, 2)(1, 3)(1, 4)
22(2, 1)(2, 2)(2, 3)(2, 4)
33(3, 1)(3, 2)(3, 3)(3, 4)
In [18]:
[[1,2,3] x]
Out[18]:
x1x1_1x2x3x4
Int64Tuple…Tuple…Tuple…Tuple…
11(1, 1)(1, 2)(1, 3)(1, 4)
22(2, 1)(2, 2)(2, 3)(2, 4)
33(3, 1)(3, 2)(3, 3)(3, 4)

다음과 같은 구문도 사용할 수 있다. 좀 장황한 감이 있지만 깔끔하다.

In [19]:
y = [x DataFrame(A=[1,2,3])]
Out[19]:
x1x2x3x4A
Tuple…Tuple…Tuple…Tuple…Int64
1(1, 1)(1, 2)(1, 3)(1, 4)1
2(2, 1)(2, 2)(2, 3)(2, 4)2
3(3, 1)(3, 2)(3, 3)(3, 4)3

아래는 같지만 :A 열이 앞에 붙는다.

In [20]:
y = [DataFrame(A=[1,2,3]) x]
Out[20]:
Ax1x2x3x4
Int64Tuple…Tuple…Tuple…Tuple…
11(1, 1)(1, 2)(1, 3)(1, 4)
22(2, 1)(2, 2)(2, 3)(2, 4)
33(3, 1)(3, 2)(3, 3)(3, 4)

또한 열을 중간에 추가할 수도 있다. 여기서는 brute-force 방법을 사용해서 새 데이터프레임을 만들었다.

In [21]:
using BenchmarkTools
@btime [$x[1:2] DataFrame(A=[1,2,3]) $x[3:4]]
  14.730 μs (120 allocations: 9.36 KiB)
Out[21]:
x1x2Ax3x4
Tuple…Tuple…Int64Tuple…Tuple…
1(1, 1)(1, 2)1(1, 3)(1, 4)
2(2, 1)(2, 2)2(2, 3)(2, 4)
3(3, 1)(3, 2)3(3, 3)(3, 4)

또한 insert!를 이용해서 데이터프레임 y:newcol을 추가할 수 있다.

In [22]:
insert!(y, 2, [1,2,3], :newcol)
Out[22]:
Anewcolx1x2x3x4
Int64Int64Tuple…Tuple…Tuple…Tuple…
111(1, 1)(1, 2)(1, 3)(1, 4)
222(2, 1)(2, 2)(2, 3)(2, 4)
333(3, 1)(3, 2)(3, 3)(3, 4)

만약에 여러 번 같은 열을 넣는다면 makeunique=true를 사용하는 것이 좋다.

In [23]:
insert!(y, 2, [1,2,3], :newcol, makeunique=true)
Out[23]:
Anewcol_1newcolx1x2x3x4
Int64Int64Int64Tuple…Tuple…Tuple…Tuple…
1111(1, 1)(1, 2)(1, 3)(1, 4)
2222(2, 1)(2, 2)(2, 3)(2, 4)
3333(3, 1)(3, 2)(3, 3)(3, 4)

@btime을 통해 시간을 확인해보면 hcat을 쓰는 것보다 insert!를 쓰는 것이 더 빠르다는 것을 알 수 있다.

In [24]:
@btime insert!(copy($x), 3, [1,2,3], :A)
  1.780 μs (17 allocations: 1.38 KiB)
Out[24]:
x1x2Ax3x4
Tuple…Tuple…Int64Tuple…Tuple…
1(1, 1)(1, 2)1(1, 3)(1, 4)
2(2, 1)(2, 2)2(2, 3)(2, 4)
3(3, 1)(3, 2)3(3, 3)(3, 4)

insert!를 사용해서 하나의 행을 오른쪽에 더 만들어보고,

In [25]:
insert!(x, ncol(x)+1, [1,2,3], :A)
Out[25]:
x1x2x3x4A
Tuple…Tuple…Tuple…Tuple…Int64
1(1, 1)(1, 2)(1, 3)(1, 4)1
2(2, 1)(2, 2)(2, 3)(2, 4)2
3(3, 1)(3, 2)(3, 3)(3, 4)3

왼쪽에 더 만들어보자.

In [26]:
insert!(x, 1, [1,2,3], :B)
Out[26]:
Bx1x2x3x4A
Int64Tuple…Tuple…Tuple…Tuple…Int64
11(1, 1)(1, 2)(1, 3)(1, 4)1
22(2, 1)(2, 2)(2, 3)(2, 4)2
33(3, 1)(3, 2)(3, 3)(3, 4)3

merge!를 이용해서 2번째 데이터프레임을 첫번째 데이터프레임에 합쳐보자(merge). 겹치는 것들은 덮어쓰기 한다.

In [27]:
df1 = DataFrame(x=1:3, y=4:6)
df2 = DataFrame(x='a':'c', z = 'd':'f', new=11:13)
df1, df2, merge!(df1, df2)
Out[27]:
(3×4 DataFrame
│ Row │ x    │ y     │ z    │ new   │
│     │ CharInt64CharInt64 │
├─────┼──────┼───────┼──────┼───────┤
│ 1   │ 'a'  │ 4     │ 'd'  │ 11    │
│ 2   │ 'b'  │ 5     │ 'e'  │ 12    │
│ 3   │ 'c'  │ 6     │ 'f'  │ 13    │, 3×3 DataFrame
│ Row │ x    │ z    │ new   │
│     │ CharCharInt64 │
├─────┼──────┼──────┼───────┤
│ 1   │ 'a'  │ 'd'  │ 11    │
│ 2   │ 'b'  │ 'e'  │ 12    │
│ 3   │ 'c'  │ 'f'  │ 13    │, 3×4 DataFrame
│ Row │ x    │ y     │ z    │ new   │
│     │ CharInt64CharInt64 │
├─────┼──────┼───────┼──────┼───────┤
│ 1   │ 'a'  │ 4     │ 'd'  │ 11    │
│ 2   │ 'b'  │ 5     │ 'e'  │ 12    │
│ 3   │ 'c'  │ 6     │ 'f'  │ 13    │)

비교를 위해서, hcat으로도 합쳐보자. 이 때, 겹치는 이름은 안 겹치도록 수정하게 된다.

In [28]:
df1 = DataFrame(x=1:3, y=4:6)
df2 = DataFrame(x='a':'c', z = 'd':'f', new=11:13)
println(df1)
println(df2)
hcat(df1, df2, makeunique=true)
3×2 DataFrame
│ Row │ x     │ y     │
│     │ Int64Int64 │
├─────┼───────┼───────┤
│ 1   │ 1     │ 4     │
│ 2   │ 2     │ 5     │
│ 3   │ 3     │ 6     │
3×3 DataFrame
│ Row │ x    │ z    │ new   │
│     │ CharCharInt64 │
├─────┼──────┼──────┼───────┤
│ 1   │ 'a'  │ 'd'  │ 11    │
│ 2   │ 'b'  │ 'e'  │ 12    │
│ 3   │ 'c'  │ 'f'  │ 13    │
Out[28]:
xyx_1znew
Int64Int64CharCharInt64
114'a''d'11
225'b''e'12
336'c''f'13
In [29]:
merge!(df1, df2)
Out[29]:
xyznew
CharInt64CharInt64
1'a'4'd'11
2'b'5'e'12
3'c'6'f'13

열의 일부만 가져오거나 열 지우기 (Subsetting/removing columns)

먼저 새로운 데이터프레임 x를 만든 다음에 x 열의 일부만 가져와서 새로운 데이터프레임을 만드는 몇 가지 방법을 알아보자.

In [30]:
x = DataFrame([(i,j) for i in 1:3, j in 1:5])
Out[30]:
x1x2x3x4x5
Tuple…Tuple…Tuple…Tuple…Tuple…
1(1, 1)(1, 2)(1, 3)(1, 4)(1, 5)
2(2, 1)(2, 2)(2, 3)(2, 4)(2, 5)
3(3, 1)(3, 2)(3, 3)(3, 4)(3, 5)

첫번째 방법은 인덱스(index)를 이용하는 방법이다.

In [31]:
x[[1,2,4,5]]
Out[31]:
x1x2x4x5
Tuple…Tuple…Tuple…Tuple…
1(1, 1)(1, 2)(1, 4)(1, 5)
2(2, 1)(2, 2)(2, 4)(2, 5)
3(3, 1)(3, 2)(3, 4)(3, 5)

혹은 열 이름을 이용하는 방법이다.

In [32]:
x[[:x1, :x4]]
Out[32]:
x1x4
Tuple…Tuple…
1(1, 1)(1, 4)
2(2, 1)(2, 4)
3(3, 1)(3, 4)

또한 논리값을 이용해서도 열을 유지하거나 제거할 수 있다. (이 때, 원래 데이터프레임의 열의 갯수와 같은 벡터가 필요하다.)

In [33]:
x[[true, false, true, false, true]]
Out[33]:
x1x3x5
Tuple…Tuple…Tuple…
1(1, 1)(1, 3)(1, 5)
2(2, 1)(2, 3)(2, 5)
3(3, 1)(3, 3)(3, 5)

여기서는 데이터프레임 형태를 유지하면서 열 하나만 선택했고,

In [34]:
x[[:x1]]
Out[34]:
x1
Tuple…
1(1, 1)
2(2, 1)
3(3, 1)

여기서는 x1 열의 원소들을 벡터로 가져왔다.

In [35]:
x[:x1]
Out[35]:
3-element Array{Tuple{Int64,Int64},1}:
 (1, 1)
 (2, 1)
 (3, 1)

열 번호로 같은 벡터를 가져올 수도 있다.

In [36]:
x[1]
Out[36]:
3-element Array{Tuple{Int64,Int64},1}:
 (1, 1)
 (2, 1)
 (3, 1)

그리고 empty!를 이용해서 내용을 다 없엘 수도 있다.

In [37]:
empty!(y)
Out[37]:

여기서는 x의 복사본을 만들었고, delete!를 이용해서 복사본의 3열을 지웠다.

In [38]:
z = copy(x)
x, delete!(z, 3)
Out[38]:
(3×5 DataFrame
│ Row │ x1     │ x2     │ x3     │ x4     │ x5     │
│     │ Tuple…Tuple…Tuple…Tuple…Tuple… │
├─────┼────────┼────────┼────────┼────────┼────────┤
│ 1   │ (1, 1) │ (1, 2) │ (1, 3) │ (1, 4) │ (1, 5) │
│ 2   │ (2, 1) │ (2, 2) │ (2, 3) │ (2, 4) │ (2, 5) │
│ 3   │ (3, 1) │ (3, 2) │ (3, 3) │ (3, 4) │ (3, 5) │, 3×4 DataFrame
│ Row │ x1     │ x2     │ x4     │ x5     │
│     │ Tuple…Tuple…Tuple…Tuple… │
├─────┼────────┼────────┼────────┼────────┤
│ 1   │ (1, 1) │ (1, 2) │ (1, 4) │ (1, 5) │
│ 2   │ (2, 1) │ (2, 2) │ (2, 4) │ (2, 5) │
│ 3   │ (3, 1) │ (3, 2) │ (3, 4) │ (3, 5) │)

이름으로 열 수정하기 (Modify column by name)

In [39]:
x = DataFrame([(i,j) for i in 1:3, j in 1:5])
Out[39]:
x1x2x3x4x5
Tuple…Tuple…Tuple…Tuple…Tuple…
1(1, 1)(1, 2)(1, 3)(1, 4)(1, 5)
2(2, 1)(2, 2)(2, 3)(2, 4)(2, 5)
3(3, 1)(3, 2)(3, 3)(3, 4)(3, 5)

다음 구문을 이용해서, 복사하지 않고 열을 수정할 수 있다.

In [40]:
x[:x1] = x[:x2]
x
Out[40]:
x1x2x3x4x5
Tuple…Tuple…Tuple…Tuple…Tuple…
1(1, 2)(1, 2)(1, 3)(1, 4)(1, 5)
2(2, 2)(2, 2)(2, 3)(2, 4)(2, 5)
3(3, 2)(3, 2)(3, 3)(3, 4)(3, 5)

우리는 또한 다음 구문을 이용해서 데이터프레임의 마지막에 새로운 열을 추가할 수 있다.

In [41]:
x[:A] = [1,2,3]
x
Out[41]:
x1x2x3x4x5A
Tuple…Tuple…Tuple…Tuple…Tuple…Int64
1(1, 2)(1, 2)(1, 3)(1, 4)(1, 5)1
2(2, 2)(2, 2)(2, 3)(2, 4)(2, 5)2
3(3, 2)(3, 2)(3, 3)(3, 4)(3, 5)3

다음 구문도 마찬가지로 마지막에 새로운 열을 추가하는 구문이다. (7은 ncol(x)+1과 같다.)

In [42]:
x[7] = 11:13
x
Out[42]:
x1x2x3x4x5Ax7
Tuple…Tuple…Tuple…Tuple…Tuple…Int64Int64
1(1, 2)(1, 2)(1, 3)(1, 4)(1, 5)111
2(2, 2)(2, 2)(2, 3)(2, 4)(2, 5)212
3(3, 2)(3, 2)(3, 3)(3, 4)(3, 5)313

열이름 찾기 (Find column name)

In [43]:
x = DataFrame([(i,j) for i in 1:3, j in 1:5])
Out[43]:
x1x2x3x4x5
Tuple…Tuple…Tuple…Tuple…Tuple…
1(1, 1)(1, 2)(1, 3)(1, 4)(1, 5)
2(2, 1)(2, 2)(2, 3)(2, 4)(2, 5)
3(3, 1)(3, 2)(3, 3)(3, 4)(3, 5)

우리는 다음 구문을 사용해서 주어진 이름이 열에 있는지 확인 할 수 있다.

In [44]:
:x1 in names(x)
Out[44]:
true

그리고 다음 구문을 사용해서 주어진 이름이 몇 번째 열 이름인지 알 수 있다.

In [45]:
findfirst(names(x) .== :x2)
Out[45]:
2

'Flux in Julia > Learning Julia (Intro_to_Julia_DFs)' 카테고리의 다른 글

06. rows (한글)  (0) 2018.10.12
06. rows  (0) 2018.10.12
05. columns  (0) 2018.10.11
04. loadsave (한글)  (0) 2018.10.10
04. loadsave  (0) 2018.10.10
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함