data.frame에 열 추가


115

아래에 data.frame이 있습니다. h_noh_no 1,2,3,4의 첫 번째 시리즈는 클래스 1이고 두 번째 시리즈 h_no는 클래스 2 등이 되도록 열 1 ( )에 따라 데이터를 분류하는 열을 추가하고 싶습니다 . 마지막 열에 표시된 것과 같은.

h_no  h_freq  h_freqsq
1     0.09091 0.008264628 1
2     0.00000 0.000000000 1
3     0.04545 0.002065702 1
4     0.00000 0.000000000 1  
1     0.13636 0.018594050 2
2     0.00000 0.000000000 2
3     0.00000 0.000000000 2
4     0.04545 0.002065702 2
5     0.31818 0.101238512 2
6     0.00000 0.000000000 2
7     0.50000 0.250000000 2 
1     0.13636 0.018594050 3 
2     0.09091 0.008264628 3
3     0.40909 0.167354628 3
4     0.04545 0.002065702 3

답변:


155

다양한 기술을 사용하여 데이터에 열을 추가 할 수 있습니다. 아래 인용문은 관련 도움말 텍스트의 "세부 정보"섹션에서 가져온 것입니다 [[.data.frame.

데이터 프레임은 여러 모드에서 인덱싱 할 수 있습니다. [[[단일 벡터 인덱스 ( x[i]또는 x[[i]]) 와 함께 사용 되면 목록 인 것처럼 데이터 프레임을 인덱싱합니다.

my.dataframe["new.col"] <- a.vector
my.dataframe[["new.col"]] <- a.vector

의 data.frame 메서드 는 목록으로 $처리 x됩니다.

my.dataframe$new.col <- a.vector

경우 [[[두 지수 (함께 사용 x[i, j]하고 x[[i, j]])들이 매트릭스를 인덱싱처럼 행동

my.dataframe[ , "new.col"] <- a.vector

에 대한 방법은 data.frame열 또는 행으로 작업하는지 여부를 지정하지 않으면 열을 의미한다고 가정합니다.


예를 들어 다음과 같이 작동합니다.

# make some fake data
your.df <- data.frame(no = c(1:4, 1:7, 1:5), h_freq = runif(16), h_freqsq = runif(16))

# find where one appears and 
from <- which(your.df$no == 1)
to <- c((from-1)[-1], nrow(your.df)) # up to which point the sequence runs

# generate a sequence (len) and based on its length, repeat a consecutive number len times
get.seq <- mapply(from, to, 1:length(from), FUN = function(x, y, z) {
            len <- length(seq(from = x[1], to = y[1]))
            return(rep(z, times = len))
         })

# when we unlist, we get a vector
your.df$group <- unlist(get.seq)
# and append it to your original data.frame. since this is
# designating a group, it makes sense to make it a factor
your.df$group <- as.factor(your.df$group)


   no     h_freq   h_freqsq group
1   1 0.40998238 0.06463876     1
2   2 0.98086928 0.33093795     1
3   3 0.28908651 0.74077119     1
4   4 0.10476768 0.56784786     1
5   1 0.75478995 0.60479945     2
6   2 0.26974011 0.95231761     2
7   3 0.53676266 0.74370154     2
8   4 0.99784066 0.37499294     2
9   5 0.89771767 0.83467805     2
10  6 0.05363139 0.32066178     2
11  7 0.71741529 0.84572717     2
12  1 0.10654430 0.32917711     3
13  2 0.41971959 0.87155514     3
14  3 0.32432646 0.65789294     3
15  4 0.77896780 0.27599187     3
16  5 0.06100008 0.55399326     3

열을 추가하는 마지막 두 가지 방법의 차이점은 무엇입니까?
huon

2
@ huon-dbaupp 쉼표가있는 메서드는 명시 적이며 행렬에서도 작동하는 반면 마지막 메서드는 data.frames에서만 작동합니다. 쉼표가 제공되지 않으면 R은 열을 의미한다고 가정합니다.
Roman Luštrik

12

쉽게 : 데이터 프레임은 A입니다.

b <- A[,1]
b <- b==1
b <- cumsum(b)

그런 다음 열 b를 얻습니다.


멋지고 짧습니다. cumsum(b) -> b결과가 아닌 원래 데이터 프레임에 열로 직접 추가 되도록 마지막 요소를 변경합니다 A$groups <- cumsum(b).
A5C1D2H2I1M1N2O1R2T1

cumsum(b)길이 3의 벡터를 줄 것입니까, 아니면 내가 뭔가를 놓치고 있습니까?
Roman Luštrik

@ RomanLuštrik, 이 경우 cumsum이 어떻게 작동하는지 설명하는 dbaupp의 솔루션 을 참조하십시오 .
A5C1D2H2I1M1N2O1R2T1

2
@ RomanLuštrik,이 솔루션은 한 줄로 정말 멋지게 다시 작성할 수 있습니다. your.df데이터를 사용하여 간단히 your.df$group = cumsum(your.df[, 1]==1)새 그룹 열을 가져올 수 있습니다.
A5C1D2H2I1M1N2O1R2T1

7

질문을 올바르게 이해하면가 h_no증가하지 않는 시기를 감지 한 다음 class. (이 문제를 어떻게 해결했는지 살펴 보겠습니다. 마지막에는 자체 기능이 있습니다.)

우리 h_no는 현재 열에 대해서만 신경 을 쓰므로 데이터 프레임에서 추출 할 수 있습니다.

> h_no <- data$h_no

우리는 h_no상승하지 않을 때를 감지하고 싶습니다 . 이것은 연속적인 요소의 차이가 음수이거나 0 일 때 알아낼 수 있습니다. R은 diff차이의 벡터를 제공하는 함수를 제공합니다.

> d.h_no <- diff(h_no)
> d.h_no
 [1]  1  1  1 -3  1  1  1  1  1  1 -6  1  1  1

일단 우리가 그것을 가지고 있으면, 양성이 아닌 것을 찾는 것은 간단한 문제입니다.

> nonpos <- d.h_no <= 0
> nonpos
 [1] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE FALSE  TRUE FALSE
[13] FALSE FALSE

R에서, TRUEand FALSE는 기본적으로 1and와 동일 0하므로 누적 합을 구하면 nonpos(거의) 적절한 지점에서 1 씩 증가합니다. cumsum(기본적으로의 반대 기능 diff)이 작업을 수행 할 수 있습니다.

> cumsum(nonpos)
 [1] 0 0 0 1 1 1 1 1 1 1 2 2 2 2

그러나 두 가지 문제가 있습니다. 숫자가 너무 적습니다. 그리고 첫 번째 요소가 누락되었습니다 (첫 번째 클래스에 4 개가 있어야 함).

첫 번째 문제는 간단히 해결 1+cumsum(nonpos)됩니다.. 두 1번째 요소는 첫 번째 요소가 항상 클래스에 있으므로 벡터 앞에 a 를 추가하면 됩니다 1.

 > classes <- c(1, 1 + cumsum(nonpos))
 > classes
  [1] 1 1 1 1 2 2 2 2 2 2 2 3 3 3 3

이제 다음 cbind을 사용하여 데이터 프레임에 다시 연결할 수 있습니다 ( class=구문 을 사용 하여 열에 class제목을 지정할 수 있음 ).

 > data_w_classes <- cbind(data, class=classes)

그리고 data_w_classes이제 결과가 포함되어 있습니다.

최종 결과

라인을 함께 압축하고 모든 것을 함수로 감싸서 사용하기 쉽게 만들 수 있습니다.

classify <- function(data) {
   cbind(data, class=c(1, 1 + cumsum(diff(data$h_no) <= 0)))
}

또는 class요소가되는 것이 타당하기 때문에 :

classify <- function(data) {
   cbind(data, class=factor(c(1, 1 + cumsum(diff(data$h_no) <= 0))))
}

다음과 같은 기능을 사용합니다.

> classified <- classify(data) # doesn't overwrite data
> data <- classify(data) # data now has the "class" column

(이 문제를 해결하는이 방법은 일반적으로 R에 권장되는 명시 적 반복을 피하고 많은 중간 벡터 및 목록 등을 생성하지 않기 때문에 좋습니다. 또한 한 줄에 작성하는 방법도 깔끔합니다. :))


2

Roman의 대답 외에도 이와 같은 것이 더 간단 할 수 있습니다. 지금은 R에 대한 액세스 권한이 없기 때문에 테스트하지 않았습니다.

# Note that I use a global variable here
# normally not advisable, but I liked the
# use here to make the code shorter
index <<- 0
new_column = sapply(df$h_no, function(x) {
  if(x == 1) index = index + 1
  return(index)
})

이 함수는의 값을 반복 n_ho하고 항상 현재 값이 속한 범주를 반환합니다. 값 1이 감지되면 전역 변수를 늘리고 index계속합니다.


나는 전역 변수를 가진 해킹을 좋아합니다. 그래서 Cish. : P
Roman Luštrik

2

"cbind"를 사용하는 것이 R의 데이터 프레임에 열을 추가하는 가장 간단한 방법이라고 생각합니다. 아래 예제 :

    myDf = data.frame(index=seq(1,10,1), Val=seq(1,10,1))
    newCol= seq(2,20,2)
    myDf = cbind(myDf,newCol)

1
Data.frame[,'h_new_column'] <- as.integer(Data.frame[,'h_no'], breaks=c(1, 4, 7))

0

식별 그룹 수 ( xin mapply) 및 길이 ( yin mapply)를 기반으로 접근

mytb<-read.table(text="h_no  h_freq  h_freqsq group
1     0.09091 0.008264628 1
2     0.00000 0.000000000 1
3     0.04545 0.002065702 1
4     0.00000 0.000000000 1  
1     0.13636 0.018594050 2
2     0.00000 0.000000000 2
3     0.00000 0.000000000 2
4     0.04545 0.002065702 2
5     0.31818 0.101238512 2
6     0.00000 0.000000000 2
7     0.50000 0.250000000 2 
1     0.13636 0.018594050 3 
2     0.09091 0.008264628 3
3     0.40909 0.167354628 3
4     0.04545 0.002065702 3", header=T, stringsAsFactors=F)
mytb$group<-NULL

positionsof1s<-grep(1,mytb$h_no)

mytb$newgroup<-unlist(mapply(function(x,y) 
  rep(x,y),                      # repeat x number y times
  x= 1:length(positionsof1s),    # x is 1 to number of nth group = g1:g3
  y= c( diff(positionsof1s),     # y is number of repeats of groups g1 to penultimate (g2) = 4, 7
        nrow(mytb)-              # this line and the following gives number of repeat for last group (g3)
          (positionsof1s[length(positionsof1s )]-1 )  # number of rows - position of penultimate group (g2) 
      ) ) )
mytb
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.