yaxt - xlab size in r




data.table에서 참조로 행을 삭제하는 방법? (4)

내 질문에 대한 참조에 의해 할당 대 data.table 복사 관련이 있습니다. 참조로 행을 삭제할 수 있는지 알고 싶습니다.

DT[ , someCol := NULL]

나는 알고 싶어한다.

DT[someRow := NULL, ]

나는이 함수가 존재하지 않는 이유에 대해 좋은 이유가 있다고 생각한다. 그래서 아마도 다음과 같이 일반적인 복사 접근법에 대한 좋은 대안을 지적 할 수있을 것이다. 특히, 예제 (data.table)에서 내 즐겨 찾기로 이동,

DT = data.table(x = rep(c("a", "b", "c"), each = 3), y = c(1, 3, 6), v = 1:9)
#      x y v
# [1,] a 1 1
# [2,] a 3 2
# [3,] a 6 3
# [4,] b 1 4
# [5,] b 3 5
# [6,] b 6 6
# [7,] c 1 7
# [8,] c 3 8
# [9,] c 6 9

이 data.table에서 첫 번째 행을 삭제하고 싶습니다. 나는 내가 이것을 할 수 있다는 것을 안다.

DT <- DT[-1, ]

set(DT, i, j, value) ...)를 찾았을 , N object.size(DT) 라면 약 3 * N 메모리가 필요하기 때문에 종종 피할 수 있습니다 . set(DT, i, j, value) . 특정 값을 설정하는 방법을 알고있다. (여기서는 행 1과 2, 열 2와 3의 모든 값을 0으로 설정)

set(DT, 1:2, 2:3, 0) 
DT
#      x y v
# [1,] a 0 0
# [2,] a 0 0
# [3,] a 6 3
# [4,] b 1 4
# [5,] b 3 5
# [6,] b 6 6
# [7,] c 1 7
# [8,] c 3 8
# [9,] c 6 9

하지만 처음 두 행을 지우려면 어떻게해야합니까? 하기

set(DT, 1:2, 1:3, NULL)

전체 DT를 NULL로 설정합니다.

내 SQL 지식은 매우 제한되어 있으므로 여러분에게 알려주십시오 : 주어진 data.table은 SQL 기술을 사용합니다. SQL 명령과 동등합니다

DELETE FROM table_name
WHERE some_column=some_value

data.table에?


@ vc273의 답과 @ Frank의 피드백을 기반으로 한 작동 함수가 있습니다.

delete <- function(DT, del.idxs) {           # pls note 'del.idxs' vs. 'keep.idxs'
  keep.idxs <- setdiff(DT[, .I], del.idxs);  # select row indexes to keep
  cols = names(DT);
  DT.subset <- data.table(DT[[1]][keep.idxs]); # this is the subsetted table
  setnames(DT.subset, cols[1]);
  for (col in cols[2:length(cols)]) {
    DT.subset[, (col) := DT[[col]][keep.idxs]];
    DT[, (col) := NULL];  # delete
  }
   return(DT.subset);
}

사용 예 :

dat <- delete(dat,del.idxs)   ## Pls note 'del.idxs' instead of 'keep.idxs'

여기서 "dat"은 data.table입니다. 1.4M 행에서 14k 행을 제거하면 노트북에서 0.25 초가 걸립니다.

> dim(dat)
[1] 1419393      25
> system.time(dat <- delete(dat,del.idxs))
   user  system elapsed 
   0.23    0.02    0.25 
> dim(dat)
[1] 1404715      25
> 

추신. 내가 처음 인 이래로 @ vc273의 스레드에 주석을 추가 할 수 없었다 :-(


다음은 내가 사용한 몇 가지 전략입니다. 나는 .ROW 함수가 올 것이라고 믿는다. 아래의 접근 방법 중 어느 것도 빠르지 않습니다. 이것들은 부분 집합이나 필터링을 약간 넘어서는 몇 가지 전략입니다. dba가 데이터를 정리하려고하는 것처럼 생각했습니다. 위에서 언급 한 것처럼 data.table에서 행을 선택하거나 제거 할 수 있습니다.

data(iris)
iris <- data.table(iris)

iris[3] # Select row three

iris[-3] # Remove row three

You can also use .SD to select or remove rows:

iris[,.SD[3]] # Select row three

iris[,.SD[3:6],by=,.(Species)] # Select row 3 - 6 for each Species

iris[,.SD[-3]] # Remove row three

iris[,.SD[-3:-6],by=,.(Species)] # Remove row 3 - 6 for each Species

주 : .SD는 원래 데이터의 서브 세트를 작성하며 j 또는 후속 data.table에서 많은 작업을 수행 할 수 있도록합니다. https://.com/a/47406952/305675 참조 https://.com/a/47406952/305675 . 여기서는 Sepal Length로 조리개를 주문하고 Sepal.Length를 최소로 지정하고 모든 Species의 세 번째 (Sepal Length 기준)를 선택하고 모든 데이터를 반환합니다.

iris[order(-Sepal.Length)][Sepal.Length > 3,.SD[1:3],by=,.(Species)]

위의 접근 방식은 행을 제거 할 때 순차적으로 data.table을 재정렬합니다. data.table을 조 변경하고 이전 된 행인 이전 행을 제거하거나 바꿀 수 있습니다. ': = NULL'을 사용하여 변환 된 행을 제거하면 후속 열 이름도 제거됩니다.

m_iris <- data.table(t(iris))[,V3:=NULL] # V3 column removed

d_iris <- data.table(t(iris))[,V3:=V2] # V3 column replaced with V2

data.frame을 다시 data.table로 조 변경 할 때 원래 data.table에서 이름을 바꾸고 삭제할 경우 클래스 속성을 복원 할 수 있습니다. 이제 ": = NULL"을 transposed 된 data.table에 적용하면 모든 문자 클래스가 생성됩니다.

m_iris <- data.table(t(d_iris));
setnames(d_iris,names(iris))

d_iris <- data.table(t(m_iris));
setnames(m_iris,names(iris))

Key의 유무에 관계없이 중복 행을 삭제하기 만하면됩니다.

d_iris[,Key:=paste0(Sepal.Length,Sepal.Width,Petal.Length,Petal.Width,Species)]     

d_iris[!duplicated(Key),]

d_iris[!duplicated(paste0(Sepal.Length,Sepal.Width,Petal.Length,Petal.Width,Species)),]  

증분 카운터에 '.I'를 추가하는 것도 가능합니다. 그런 다음 중복 키 또는 필드를 검색하여 카운터로 레코드를 제거하여 제거 할 수 있습니다. 이것은 계산 비용이 많이 들지만 제거 할 선을 인쇄 할 수 있으므로 몇 가지 장점이 있습니다.

d_iris[,I:=.I,] # add a counter field

d_iris[,Key:=paste0(Sepal.Length,Sepal.Width,Petal.Length,Petal.Width,Species)]

for(i in d_iris[duplicated(Key),I]) {print(i)} # See lines with duplicated Key or Field

for(i in d_iris[duplicated(Key),I]) {d_iris <- d_iris[!I == i,]} # Remove lines with duplicated Key or any particular field.

0 또는 NAs로 행을 채우고 i 쿼리를 사용하여 삭제할 수도 있습니다.

 X 
   x v foo
1: c 8   4
2: b 7   2

X[1] <- c(0)

X
   x v foo
1: 0 0   0
2: b 7   2

X[2] <- c(NA)
X
    x  v foo
1:  0  0   0
2: NA NA  NA

X <- X[x != 0,]
X <- X[!is.na(x),]

메모리 사용을 비슷한 장소에서 삭제하기 위해 취한 접근법은 한 번에 열을 부분 집합하고 삭제하는 것입니다. 적절한 C memmove 솔루션만큼 빠르지는 않지만 메모리 사용은 내가 여기서 신경 쓰는 것입니다. 이 같은:

DT = data.table(col1 = 1:1e6)
cols = paste0('col', 2:100)
for (col in cols){ DT[, (col) := 1:1e6] }
keep.idxs = sample(1e6, 9e5, FALSE) # keep 90% of entries
DT.subset = data.table(col1 = DT[['col1']][keep.idxs]) # this is the subsetted table
for (col in cols){
  DT.subset[, (col) := DT[[col]][keep.idxs]]
  DT[, (col) := NULL] #delete
}

좋은 질문. data.table 은 아직 참조로 행을 삭제할 수 없습니다.

data.table 은 알다시피 열 포인터의 벡터를 너무 많이 할당하므로 참조로 을 추가 및 삭제할 수 있습니다. 계획은 행에 대해 유사한 작업을 수행하고 빠른 insertdelete 허용하는 것입니다. 행 삭제는 C에서 memmove 를 사용하여 삭제 된 행 뒤의 항목 (각 열마다)을 바꾼다. 테이블 중간에서 행을 삭제하면 SQL과 같은 행 저장소 데이터베이스와 비교할 때 여전히 비효율적입니다. SQL은 행이 테이블에있는 모든 위치에서 빠른 삽입 및 삭제에 더 적합합니다. 그러나 여전히 삭제 된 행을 제외하고 새로운 대형 객체를 복사하는 것보다 훨씬 빠릅니다.

반면에 열 벡터는 너무 많이 할당되므로 행을 즉시 끝에 삽입 (및 삭제) 할 수 있습니다. 예를 들어 성장하는 시계열.

문제로 제기되었습니다. 행을 참조로 삭제합니다 .





data.table