R 데이터에서 이전 행의 값을 사용합니다.


81

한 열의 현재 값과 다른 열의 이전 값에서 계산 된 data.table에 새 열을 만들고 싶습니다. 이전 행에 액세스 할 수 있습니까?

예 :

> DT <- data.table(A=1:5, B=1:5*10, C=1:5*100)
> DT
   A  B   C
1: 1 10 100
2: 2 20 200
3: 3 30 300
4: 4 40 400
5: 5 50 500
> DT[, D := C + BPreviousRow] # What is the correct code here?

정답은

> DT
   A  B   C   D
1: 1 10 100  NA
2: 2 20 200 210
3: 3 30 300 320
4: 4 40 400 430
5: 5 50 500 540

난 보통 내 data.tables에 키를 설정 :DT <- data.table(A=..., key = "A")
PatrickT

답변:


103

v1.9.6 에서 shift()구현 하면 이것은 매우 간단합니다.

DT[ , D := C + shift(B, 1L, type="lag")]
# or equivalently, in this case,
DT[ , D := C + shift(B)]

에서 뉴스 :

  1. 새로운 기능의 shift()빠른 구현 lead/lag벡터 , 리스트 , data.frames 또는 data.tables . "lag" (기본값) 또는 "lead"type 중 하나 일 수 있는 인수를 사용 합니다. 그것은과 함께 매우 편리한 사용 가능 또는 . 예 : . 더 많은 정보 를 위해 봐주세요 .:=set()DT[, (cols) := shift(.SD, 1L), by=id]?shift

이전 답변에 대한 기록을 참조하십시오.


.N현재 행 번호 또는 무언가 를 보유하고 있습니까? 여기에서 물어 보셔서 죄송합니다. 도움말 파일에서 찾을 수없는 것 같습니다 ...
SlowLearner 2013-02-04

7
@SlowLearner : .Icurren 그룹의 행에 대한 행 인덱스를 보유하는 유용함 을 찾을 수도 있습니다 .
Steve Lianoglou 2013

7
1 :(. N-1) 대신 seq_len (.N-1)을 사용하십시오. 이렇게하면 1 : 0과 관련된 문제를 방지 할 수 있습니다.
mnel 2013

1
.SD예를 들어 +1 -a를 사용하여 lapply펑키 한 결과를 얻었습니다. 이것은 훨씬 더 간단합니다.
MichaelChirico

이 모든 새로운 정보가 포함 된 업데이트 된 PDF는 어디에서 찾을 수 있습니까? 공식 1.9.4 비 네트와 웹 미나에는 포함되어 있지 않습니다. 그리고 Rmd 1.9.5 비 네트는 편안하지 않으며 포함하지도 않습니다.
skan 2015

44

사용하면 dplyr다음을 수행 할 수 있습니다.

mutate(DT, D = lag(B) + C)

다음을 제공합니다.

#   A  B   C   D
#1: 1 10 100  NA
#2: 2 20 200 210
#3: 3 30 300 320
#4: 4 40 400 430
#5: 5 50 500 540

22

몇몇 사람들이 구체적인 질문에 답했습니다. 도움이 될 수있는 이와 같은 상황에서 사용하는 범용 함수는 아래 코드를 참조하십시오. 이전 행을 가져 오는 대신 "과거"또는 "미래"에서 원하는만큼 많은 행으로 이동할 수 있습니다.

rowShift <- function(x, shiftLen = 1L) {
  r <- (1L + shiftLen):(length(x) + shiftLen)
  r[r<1] <- NA
  return(x[r])
}

# Create column D by adding column C and the value from the previous row of column B:
DT[, D := C + rowShift(B,-1)]

# Get the Old Faithul eruption length from two events ago, and three events in the future:
as.data.table(faithful)[1:5,list(eruptLengthCurrent=eruptions,
                                 eruptLengthTwoPrior=rowShift(eruptions,-2), 
                                 eruptLengthThreeFuture=rowShift(eruptions,3))]
##   eruptLengthCurrent eruptLengthTwoPrior eruptLengthThreeFuture
##1:              3.600                  NA                  2.283
##2:              1.800                  NA                  4.533
##3:              3.333               3.600                     NA
##4:              2.283               1.800                     NA
##5:              4.533               3.333                     NA

이것은 훌륭한 답변입니다. 이것은 훨씬 더 일반적인 답변이기 때문에 이미 다른 답변에 찬성 투표를 한 것에 짜증이납니다. 사실, 제 제노 라마 패키지에서 사용할 것입니다 (괜찮다면).
geneorama

물론입니다. 나는 약간의 자유 시간을 얻고로 끌어 오기 요청으로 증명서를 제출하는 것은 기대했다 data.table패키지, 그러나 슬프 도다 ...
dnlbrky

라는 유사한 함수 가 버전 1.9.5 shift부터 추가되었습니다 data.table. @Arun 의 업데이트 된 답변 을 참조하십시오 .
dnlbrky

12

위의 @Steve Lianoglou의 의견에 따라 다음과 같은 이유가 있습니다.

DT[, D:= C + c(NA, B[.I - 1]) ]
#    A  B   C   D
# 1: 1 10 100  NA
# 2: 2 20 200 210
# 3: 3 30 300 320
# 4: 4 40 400 430
# 5: 5 50 500 540

seq_len또는 head또는 다른 기능을 사용하지 마십시오 .


2
니스-그러나 그룹 내에서 이전을 찾으려면 작동하지 않습니다.
Matthew

1
@Matthew 당신이 맞습니다. 그룹별로 부분 집합 화하면 다음으로 대체 .I됩니다.seq_len(.N)
Gary Weissman

9

Arun의 솔루션에 따라 다음을 참조하지 않고도 유사한 결과를 얻을 수 있습니다. .N

> DT[, D := C + c(NA, head(B, -1))][]
   A  B   C   D
1: 1 10 100  NA
2: 2 20 200 210
3: 3 30 300 320
4: 4 40 400 430
5: 5 50 500 540

한 방법을 다른 방법보다 선호하는 이유가 있습니까? 아니면 단순히 미학적 차이일까요?
Korone 2013

나는이 시나리오 (즉, .N쉽게 구할 수 있는 곳 )에서 대부분 미학적 선택 이라고 생각합니다 . 나는 중요한 차이점을 인식하지 못합니다.
Ryogi 2013


1

내 직관적 인 솔루션은 다음과 같습니다.

#create data frame
df <- data.frame(A=1:5, B=seq(10,50,10), C=seq(100,500, 100))`
#subtract the shift from num rows
shift  <- 1 #in this case the shift is 1
invshift <- nrow(df) - shift
#Now create the new column
df$D <- c(NA, head(df$B, invshift)+tail(df$C, invshift))`

여기서 invshift행 수에서 1을 뺀 값은 4 nrow(df)입니다. 데이터 프레임이나 벡터의 행 수를 제공합니다. 마찬가지로 이전 값을 가져 오려면 nrow 2, 3, ... etc에서 빼고 그에 따라 NA를 처음에 넣으십시오.


-2

루프에서 수행 할 수 있습니다.

# Create the column D
DT$D <- 0
# for every row in DT
for (i in 1:length(DT$A)) {
  if(i==1) {
    #using NA at first line
    DT[i,4] <- NA
  } else {
    #D = C + BPreviousRow
    DT[i,4] <- DT[i,3] + DT[(i-1), 2]   
  }
}

for를 사용하면이 새 열 행의 이전 값을 사용할 수도 있습니다. DT[(i-1), 4]

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.