기본 콘텐츠로 건너뛰기

[matplotlib]quiver()함수

apply group_R

apply_do

1 Apply group

1.1 apply()

apply()함수 계열을 for, while 등의 루프(loop)문의 기능을 하는 R의 내장함수이다. 이 계열의 함수는 객체와 함수를 기본 매계변수로 전달된다.
apply(x, margin, FUN)
배열 또는 행렬 객체에 함수를 적용하기 위한 함수로서 적용할 함수가 객체의 행 또는 열을 지정해야 된다. 인수중 margin은 이 방향을 의미한다. 즉, 인수 1은 행, 2는 열방향을 의미한다.
다음의 데이터는 kospi의 일일 주가자료이다.
> kospi<-read.csv('kospi1.csv')
> tail(kospi, 3)
           date      op      hp      lp      cp    vol
1829 2017-06-13 2358.92 2375.81 2358.92 2374.70 322081
1830 2017-06-14 2384.54 2387.29 2366.92 2372.64 386990
1831 2017-06-15 2373.36 2378.04 2350.37 2361.65 331182
위 자료의 date를 제외한 각 열의 평균을 산정하기 위해 apply() 함수를 사용한다. R에서 평균을 계산하기 위해 mean()를 적용한다.
> apply(kospi[,-1], 2, mean ) #각 열의 평균으로 다음의 cloMeans()와 동일하다.  
        op         hp         lp         cp        vol 
  1959.625   1967.838   1948.458   1958.643 380240.086 
> colMeans(kospi[,-1])
        op         hp         lp         cp        vol 
  1959.625   1967.838   1948.458   1958.643 380240.086 
> tail(apply(kospi[,-1], 1,  sum), 3) #각 행의 합 
[1] 331549.3 396501.4 340645.4
행렬, 배열의 각 행 또는 열 단위로 합과 평균을 계산하기 위해 ColSums(), rowSums(), colMeans(), rowMeans()가 있다.

1.2 lapply()

함수는 지정되는 객체에 특정한 함수를 적용하여 그 결과를 리스트로 반환한다.
lapply(x, FUN, …)
벡터, 리스트, 표현식, 데이터 프레임(x) 등에서 함수(FUN)를 적용하고 그 결과를 리스트로 반환한다. … 는 FUN의 인자들로서 입력된 값은 FUN으로 전달된다. 반환값은 리스트다.
객체 x의 각각의 함수의 적용 대상으로 간주한다. 반환값 리스트는 unlist(x, recursive=FALSE, use.names=TRUE)를 이용하여 벡터 구조로 전환한다.
함수의 매개변수 중 recursive=FALSE는 x에 포함된 리스트 역시 재귀적으로 변환할지 여부를 지정하고, use.names=TRUE 리스트 내 값의 이름을 보존할 지 여부를 지정하는 것이다. 디폴트 값으로 원 객체의 이름이 유지된다.
> simpleStatistics.s<-function(x){
+   return(list("Sum"=sum(x), "Quantile"=mean(x)))
+ }
> 
> x<-lapply(2:ncol(kospi), function(i){simpleStatistics.s(kospi[,i])} )
> names(x)<-colnames(kospi[,-1])
> x
$op
$op$Sum
[1] 3588073

$op$Quantile
[1] 1959.625


$hp
$hp$Sum
[1] 3603112

$hp$Quantile
[1] 1967.838


$lp
$lp$Sum
[1] 3567627

$lp$Quantile
[1] 1948.458


$cp
$cp$Sum
[1] 3586274

$cp$Quantile
[1] 1958.643


$vol
$vol$Sum
[1] 696219597

$vol$Quantile
[1] 380240.1
> unlist(x) #결과 구조인 리스트는 unlist() 적용으로 벡터 구조로 전환된다. 
      op.Sum  op.Quantile       hp.Sum  hp.Quantile       lp.Sum 
3.588073e+06 1.959625e+03 3.603112e+06 1.967838e+03 3.567627e+06 
 lp.Quantile       cp.Sum  cp.Quantile      vol.Sum vol.Quantile 
1.948458e+03 3.586274e+06 1.958643e+03 6.962196e+08 3.802401e+05 

1.3 do.call()

리스트 구조의 객체에 unlist()를 사용하여 벡터 구조로 전환할 경우 각 객체에 이질적인 데이터 형이 존재하면 원 데이터 형은 유지되지 못하고 한가지로 전환된다. 그러므로 각 데이터의 형을 유지할 필요가 있다. 이러한 경우 사용할 수 있는 함수가 apply() 함수와 유사한 기능을 하는 do.call() 함수로 리스트로 되어 있는 객체의 각 원소에 지정된 함수를 적용한다.
do.call(Fun, list구조의 데이터)
리스트 구조의 데이터에 함수를 적용한다.
위이 결과 x는 리스트이다. 이 리스트의 각 원소객체를 열 단위로 합하여 행렬의 형태로 나타내기 위해 다음과 같이 실행한다.
> do.call(cbind, x) # 리스트 객체의 각 원소객체를 열 단위로 결합 
         op       hp       lp       cp       vol      
Sum      3588073  3603112  3567627  3586274  696219597
Quantile 1959.625 1967.838 1948.458 1958.643 380240.1 
> do.call(rbind, x) # 행단위로 결합 
    Sum       Quantile
op  3588073   1959.625
hp  3603112   1967.838
lp  3567627   1948.458
cp  3586274   1958.643
vol 696219597 380240.1
> y<-do.call(rbind, x)
> y
    Sum       Quantile
op  3588073   1959.625
hp  3603112   1967.838
lp  3567627   1948.458
cp  3586274   1958.643
vol 696219597 380240.1
> class(y)
[1] "matrix"
> x<-list(data.frame(name="foo", value =1), data.frame(name="bar", value=2))
> x
[[1]]
  name value
1  foo     1

[[2]]
  name value
1  bar     2
> unlist(x)
 name value  name value 
    1     1     1     2 
> class(unlist(x))
[1] "numeric"
> y<-do.call(rbind, x)
> y
  name value
1  foo     1
2  bar     2
> class(y)
[1] "data.frame"

1.4 sapply()

sapply(객체, 함수, …)
벡터, 리스트, 표현식, 데이터프레임 등의 객체에 함수를 적용하고 그 결과를 벡터 또는 행렬로 반환한다.
결과의 길이가 1이면 벡터, 1보다 크면 행렬로 반환된다.
> x<-lapply(kospi[,-1], mean)
> x #리스트 구조 
$op
[1] 1959.625

$hp
[1] 1967.838

$lp
[1] 1948.458

$cp
[1] 1958.643

$vol
[1] 380240.1
> y<-sapply(kospi[,-1], mean)
> y # 벡터 구조 
        op         hp         lp         cp        vol 
  1959.625   1967.838   1948.458   1958.643 380240.086 
> x<-lapply(2:ncol(kospi), function(i){simpleStatistics.s(kospi[,i])})
> x
[[1]]
[[1]]$Sum
[1] 3588073

[[1]]$Quantile
[1] 1959.625


[[2]]
[[2]]$Sum
[1] 3603112

[[2]]$Quantile
[1] 1967.838


[[3]]
[[3]]$Sum
[1] 3567627

[[3]]$Quantile
[1] 1948.458


[[4]]
[[4]]$Sum
[1] 3586274

[[4]]$Quantile
[1] 1958.643


[[5]]
[[5]]$Sum
[1] 696219597

[[5]]$Quantile
[1] 380240.1
> class(x)
[1] "list"
> y<-sapply(2:ncol(kospi), function(i){simpleStatistics.s(kospi[,i])})
> y
         [,1]     [,2]     [,3]     [,4]     [,5]     
Sum      3588073  3603112  3567627  3586274  696219597
Quantile 1959.625 1967.838 1948.458 1958.643 380240.1 
> class(y)
[1] "matrix"
sapply()는 한가지 타입만 저장 가능한 데이터 타입인 벡터 또는 행렬을 반환하므로 함수의 반환값이 여러 데이터형을 가지면 안된다. 이 경우는 lapply()를 사용해야 한다.

1.5 tapply()

데이터를 일정한 기준에 의해 그룹화하여 각 그룹에 지정된 함수를 적용하기 위해 사용한다.
tapply(객체, index, FUN,…)
백터인 객체를 index로 전달된 기준으로 그룹화하여 각 그룹에 FUN(함수)를 적용아려 그 결과를 배열로 반환한다.
위 kospi 자료의 2열과 5열을 비교하여 0보다 크면 1, 작으면 0으로 구분할 경우 각각에서의 vol의 mean을 계산한 것이다.
> kos<-data.frame(kospi, id=ifelse(kospi[,5]>kospi[,2], 1, 0))
> tail(kos, 3)
           date      op      hp      lp      cp    vol id
1829 2017-06-13 2358.92 2375.81 2358.92 2374.70 322081  1
1830 2017-06-14 2384.54 2387.29 2366.92 2372.64 386990  0
1831 2017-06-15 2373.36 2378.04 2350.37 2361.65 331182  0
> tapply(kos$vol, kos$id, mean)
       0        1 
383950.9 376194.7 

1.6 mapply()

apply()와 유사한 계열의 함수는 결과적으로 데이터의 특정한 부분에 지정한 함수를 적용하기 위해 사용한다. 그러나 apply와 sapply의 경우 적용하는 함수에 전달하는 인수가 여러개일 경우 사용이 용이하지 않다. 이러한 경우에 사용할 수 있는 함수가 mapply()이다.
mapply(FUN, 인수1, 인수2, …)
함수에 적용되는 인수가 여러개 일 경우 사용한다. 결과는 리스트이다.
rnorm(갯수, 평균, 표준편차)는 전달한 평균과 표준편차를 가지는 정규분포를 따르는 지정한 수만큼의 랜덤수를 산출하는 함수이다. 이 산출과정에서 mapply()를 적용하여 보자.
> mapply(rnorm, c(1,2,3), c(0, 10, 100), c(1,1,1))
[[1]]
[1] -0.5301171

[[2]]
[1] 10.64874 10.00448

[[3]]
[1]  99.33829 103.26205 100.88152

2 doBy group

doBy 패키지로 부터의 데이터를 그룹화하는 함수

2.1 orderBy()

지정된 칼럼값에 따라 data.frame을 정렬한다. 유사한 함수로는 R의 내장함수인 sort(), order()가 있다.
order(data, na.last=TRUE, decreasing=FALSE)
데이터를 정렬한다.
na.last=TRUE는 기본값으로 NA 값을 정렬한 자료의 마지막에 위치한다는 의미이고 FALSE는 처음에 위치시킨다.
또한 na.last=NA는 정렬결과에서 NA 값 제외시킨다. decreaseing은 내림차순여부를 나타내는 것으로 기본은 올림차순이다.
반환값은 원 데이터에 색인(index)이다.
sort(x, decreasing=T)
벡터를 정렬할 목적으로 order()와 유사하지만 값자체가 반환된다.
> x<-round(rnorm(10),0)
> x
 [1]  0 -1  1 -1 -1  1  1 -2  1 -1
> order(x) #각 값의 인덱스를 나타냄 
 [1]  8  2  4  5 10  1  3  6  7  9
> sort(x)
 [1] -2 -1 -1 -1 -1  0  1  1  1  1
> x[order(x)] #벡터의 각 원소의 호출은 각 원소의 인덱스에 의해 이루어진다. 
 [1] -2 -1 -1 -1 -1  0  1  1  1  1
위의 함수들과 유사하지만 사용 용도가 확대된 함수가 orderBy() 함수이다.
orderBy(formula, data)
정렬할 데이터(data)를 지정한 formula에 의해 올림차순으로 정렬한다. 반환값은 정렬된 데이터이다.
kospi 자료중 최종일 기준으로 10를 샘플링하여 위 함수를 적용해 본다.
> n<-nrow(kospi)
> kospi1<-kospi[(n-10):n, ]
> kospi1
           date      op      hp      lp      cp    vol
1821 2017-05-31 2339.25 2355.23 2338.25 2347.38 555939
1822 2017-06-01 2348.31 2351.31 2335.63 2344.61 331956
1823 2017-06-02 2353.77 2372.65 2353.45 2371.72 392800
1824 2017-06-05 2376.66 2376.83 2363.61 2368.62 326411
1825 2017-06-07 2364.96 2369.43 2356.71 2360.14 370971
1826 2017-06-08 2361.64 2365.52 2347.62 2362.80 397935
1827 2017-06-09 2371.22 2385.15 2367.81 2381.69 511622
1828 2017-06-12 2370.69 2374.70 2353.35 2357.87 324051
1829 2017-06-13 2358.92 2375.81 2358.92 2374.70 322081
1830 2017-06-14 2384.54 2387.29 2366.92 2372.64 386990
1831 2017-06-15 2373.36 2378.04 2350.37 2361.65 331182
다음은 kospi1을 cp를 기준으로 정렬한다.
> library(doBy)
> orderBy(~cp, kospi1)
           date      op      hp      lp      cp    vol
1822 2017-06-01 2348.31 2351.31 2335.63 2344.61 331956
1821 2017-05-31 2339.25 2355.23 2338.25 2347.38 555939
1828 2017-06-12 2370.69 2374.70 2353.35 2357.87 324051
1825 2017-06-07 2364.96 2369.43 2356.71 2360.14 370971
1831 2017-06-15 2373.36 2378.04 2350.37 2361.65 331182
1826 2017-06-08 2361.64 2365.52 2347.62 2362.80 397935
1824 2017-06-05 2376.66 2376.83 2363.61 2368.62 326411
1823 2017-06-02 2353.77 2372.65 2353.45 2371.72 392800
1830 2017-06-14 2384.54 2387.29 2366.92 2372.64 386990
1829 2017-06-13 2358.92 2375.81 2358.92 2374.70 322081
1827 2017-06-09 2371.22 2385.15 2367.81 2381.69 511622
다음은 여러개의 기준일 경우 틸트(물결모양)기호에 가까운 변수에 의해 먼저 정렬되고 그 다음ㅔ 있는 변수가 기준이 되는 방식으로 이루어진다.
> orderBy(~cp+vol, kospi1)
           date      op      hp      lp      cp    vol
1822 2017-06-01 2348.31 2351.31 2335.63 2344.61 331956
1821 2017-05-31 2339.25 2355.23 2338.25 2347.38 555939
1828 2017-06-12 2370.69 2374.70 2353.35 2357.87 324051
1825 2017-06-07 2364.96 2369.43 2356.71 2360.14 370971
1831 2017-06-15 2373.36 2378.04 2350.37 2361.65 331182
1826 2017-06-08 2361.64 2365.52 2347.62 2362.80 397935
1824 2017-06-05 2376.66 2376.83 2363.61 2368.62 326411
1823 2017-06-02 2353.77 2372.65 2353.45 2371.72 392800
1830 2017-06-14 2384.54 2387.29 2366.92 2372.64 386990
1829 2017-06-13 2358.92 2375.81 2358.92 2374.70 322081
1827 2017-06-09 2371.22 2385.15 2367.81 2381.69 511622

2.2 summaryBy()

summaryBy(formula, data, FUN=mean)
데이터프라임을 컬럼값에 따라 그룹으로 묶은 후 지정된 함수 계산결과를 반환한다. 적용할 함수는 리스트로 여러개를 전달할 수 있다.
이 예를 보이기 위해 cut()함수를 사용하여 데이터들을 그룹화할 요인(factor)를 생성한다. 이 함수는 다음과 같다.
cut(객체, 그룹 갯수, labels = NULL, …)
객체를 지정된 갯수만큼 구분하기 위한 요인을 생성하고 label은 각 그룹의 이름으로 기본값은 없다.
kospi의 op와 cp의 변화율에 따른 요인을 생성해보자.
> ind<-cut((kospi[,5]-kospi[,2])/(kospi[,2]), 10, labels=letters[1:10])                                     
> kospi2<-data.frame(kospi[,2:5], ind)
> head(kospi2)
       op      hp      lp      cp ind
1 1681.71 1696.14 1681.71 1696.14   f
2 1701.62 1702.39 1686.45 1690.62   d
3 1697.88 1706.89 1696.10 1705.32   e
4 1702.92 1707.90 1683.45 1683.45   d
5 1694.06 1695.26 1668.84 1695.26   e
6 1700.79 1705.73 1694.12 1694.12   e
> summaryBy(op+hp+lp+cp~ind, kospi2)
   ind  op.mean  hp.mean  lp.mean  cp.mean
1    a 1866.483 1866.660 1779.717 1794.730
2    b 1867.266 1873.186 1811.085 1819.629
3    c 1928.282 1931.911 1890.320 1896.613
4    d 1963.093 1966.097 1943.411 1948.314
5    e 1973.152 1979.281 1964.809 1973.011
6    f 1938.519 1955.463 1934.370 1952.811
7    g 1894.848 1926.465 1890.738 1924.462
8    h 1810.133 1856.624 1805.083 1854.740
9    i 1713.100 1769.750 1706.900 1769.290
10   j 1733.920 1832.480 1733.920 1817.440
기본적으로 지정된 함수는 mean이고 다른 함수를 전달할 경우 반드시 매개변수명과 함께 FUN=함수이름의 형식으로 입력해야 한다. 또한 여러개의 함수를 적용할 경우 함수는 리스트형식으로 전달해야 한다.
> summaryBy(op+hp+lp+cp~ind, kospi2, FUN=list(mean, var, length))
   ind  op.mean  hp.mean  lp.mean  cp.mean    op.var    hp.var    lp.var
1    a 1866.483 1866.660 1779.717 1794.730 19836.656 19759.378 15837.629
2    b 1867.266 1873.186 1811.085 1819.629  9486.238  9717.001  9156.205
3    c 1928.282 1931.911 1890.320 1896.613 20865.606 20617.304 21048.850
4    d 1963.093 1966.097 1943.411 1948.314 17086.905 17101.602 16946.535
5    e 1973.152 1979.281 1964.809 1973.011 13259.935 13213.023 13370.683
6    f 1938.519 1955.463 1934.370 1952.811 20983.920 20983.836 21186.670
7    g 1894.848 1926.465 1890.738 1924.462 16861.964 17598.223 17308.392
8    h 1810.133 1856.624 1805.083 1854.740 15800.862 15784.125 15983.309
9    i 1713.100 1769.750 1706.900 1769.290        NA        NA        NA
10   j 1733.920 1832.480 1733.920 1817.440        NA        NA        NA
      cp.var op.length hp.length lp.length cp.length
1  18667.510         3         3         3         3
2   9395.821        18        18        18        18
3  20306.575        50        50        50        50
4  16895.609       372       372       372       372
5  13204.445      1000      1000      1000      1000
6  21134.075       338       338       338       338
7  17598.561        41        41        41        41
8  16175.419         7         7         7         7
9         NA         1         1         1         1
10        NA         1         1         1         1
summaryBy()와 유사한 함수로 tapply()를 적용할 수 있지만 적용하는 객체는 벡터이어야 한다.
> tapply(kospi2[,1], kospi2$ind, length)
   a    b    c    d    e    f    g    h    i    j 
   3   18   50  372 1000  338   41    7    1    1 

2.3 sampleBy()

sampleBy(formula, frac=0.1, replace=False, data, systematic=FALSE)
데이터 프레임을 특정 컬럼값에 따라 그룹으로 묶은 후 각 그룹에서 샘플을 추출
지정한 formula에 대해 일정한 비율(frac) 만큼 추출한다. systematic은 계통추출을 위한 인수이다. 예로서 formula ~ind 라면 각 데이터를 ind에 의해 분리하여 각 분리된 자료에서 일정한 비율을 추출한다.
> kospi2Sample<-sampleBy(~ind, frac=0.1, replace=F, data=kospi2)
> head(kospi2Sample, 2)
          op      hp      lp      cp ind
f.1  1681.71 1696.14 1681.71 1696.14   f
f.41 1615.25 1622.63 1611.35 1622.44   f
> tail(kospi2Sample, 2)
           op      hp      lp      cp ind
b.416 1829.30 1829.75 1785.82 1785.83   b
b.461 1860.96 1862.27 1813.25 1813.25   b

댓글

이 블로그의 인기 게시물

[Linear Algebra] 유사변환(Similarity transformation)

유사변환(Similarity transformation) n×n 차원의 정방 행렬 A, B 그리고 가역 행렬 P 사이에 식 1의 관계가 성립하면 행렬 A와 B는 유사행렬(similarity matrix)이 되며 행렬 A를 가역행렬 P와 B로 분해하는 것을 유사 변환(similarity transformation) 이라고 합니다. $$\tag{1} A = PBP^{-1} \Leftrightarrow P^{-1}AP = B $$ 식 2는 식 1의 양변에 B의 고유값을 고려한 것입니다. \begin{align}\tag{식 2} B - \lambda I &= P^{-1}AP – \lambda P^{-1}P\\ &= P^{-1}(AP – \lambda P)\\ &= P^{-1}(A - \lambda I)P \end{align} 식 2의 행렬식은 식 3과 같이 정리됩니다. \begin{align} &\begin{aligned}\textsf{det}(B - \lambda I ) & = \textsf{det}(P^{-1}(AP – \lambda P))\\ &= \textsf{det}(P^{-1}) \textsf{det}((A – \lambda I)) \textsf{det}(P)\\ &= \textsf{det}(P^{-1}) \textsf{det}(P) \textsf{det}((A – \lambda I))\\ &= \textsf{det}(A – \lambda I)\end{aligned}\\ &\begin{aligned}\because \; \textsf{det}(P^{-1}) \textsf{det}(P) &= \textsf{det}(P^{-1}P)\\ &= \textsf{det}(I)\end{aligned}\end{align} 유사행렬의 특성 유사행렬인 두 정방행렬 A와 B는 'A ~ B' 와 같...

[sympy] Sympy객체의 표현을 위한 함수들

Sympy객체의 표현을 위한 함수들 General simplify(x): 식 x(sympy 객체)를 간단히 정리 합니다. import numpy as np from sympy import * x=symbols("x") a=sin(x)**2+cos(x)**2 a $\sin^{2}{\left(x \right)} + \cos^{2}{\left(x \right)}$ simplify(a) 1 simplify(b) $\frac{x^{3} + x^{2} - x - 1}{x^{2} + 2 x + 1}$ simplify(b) x - 1 c=gamma(x)/gamma(x-2) c $\frac{\Gamma\left(x\right)}{\Gamma\left(x - 2\right)}$ simplify(c) $\displaystyle \left(x - 2\right) \left(x - 1\right)$ 위의 예들 중 객체 c의 감마함수(gamma(x))는 확률분포 등 여러 부분에서 사용되는 표현식으로 다음과 같이 정의 됩니다. 감마함수는 음이 아닌 정수를 제외한 모든 수에서 정의됩니다. 식 1과 같이 자연수에서 감마함수는 factorial(!), 부동소수(양의 실수)인 경우 적분을 적용하여 계산합니다. $$\tag{식 1}\Gamma(n) =\begin{cases}(n-1)!& n:\text{자연수}\\\int^\infty_0x^{n-1}e^{-x}\,dx& n:\text{부동소수}\end{cases}$$ x=symbols('x') gamma(x).subs(x,4) $\displaystyle 6$ factorial 계산은 math.factorial() 함수를 사용할 수 있습니다. import math math.factorial(3) 6 a=gamma(x).subs(x,4.5) a.evalf(3) 11.6 simpilfy() 함수의 알고리즘은 식에서 공통사항을 찾아 정리하...

sympy.solvers로 방정식해 구하기

sympy.solvers로 방정식해 구하기 대수 방정식을 해를 계산하기 위해 다음 함수를 사용합니다. sympy.solvers.solve(f, *symbols, **flags) f=0, 즉 동차방정식에 대해 지정한 변수의 해를 계산 f : 식 또는 함수 symbols: 식의 해를 계산하기 위한 변수, 변수가 하나인 경우는 생략가능(자동으로 인식) flags: 계산 또는 결과의 방식을 지정하기 위한 인수들 dict=True: {x:3, y:1}같이 사전형식, 기본값 = False set=True :{(x,3),(y,1)}같이 집합형식, 기본값 = False ratioal=True : 실수를 유리수로 반환, 기본값 = False positive=True: 해들 중에 양수만을 반환, 기본값 = False 예 $x^2=1$의 해를 결정합니다. solve() 함수에 적용하기 위해서는 다음과 같이 식의 한쪽이 0이 되는 형태인 동차식으로 구성되어야 합니다. $$x^2-1=0$$ import numpy as np from sympy import * x = symbols('x') solve(x**2-1, x) [-1, 1] 위 식은 계산 과정은 다음과 같습니다. $$\begin{aligned}x^2-1=0 \rightarrow (x+1)(x-1)=0 \\ x=1 \; \text{or}\; -1\end{aligned}$$ 예 $x^4=1$의 해를 결정합니다. solve() 함수의 인수 set=True를 지정하였으므로 결과는 집합(set)형으로 반환됩니다. eq=x**4-1 solve(eq, set=True) ([x], {(-1,), (-I,), (1,), (I,)}) 위의 경우 I는 복소수입니다.즉 위 결과의 과정은 다음과 같습니다. $$x^4-1=(x^2+1)(x+1)(x-1)=0 \rightarrow x=\pm \sqrt{-1}, \; \pm 1=\pm i,\; \pm1$$ 실수...