data.table에서 참조로 행을 삭제하는 방법은 무엇입니까?
내 질문은 참조 대 복사 및 복사와 관련이 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, ]
하지만 종종 우리는 객체를 복사하고 있기 때문에 우리는이를 방지 할 수 있습니다 (N은 경우 즉, 3 * N 메모리에 대한 요구 object.size(DT)
, 여기에서 지적했듯이 지금은 발견했다. 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에?
좋은 질문. data.table
아직 참조로 행을 삭제할 수 없습니다.
data.table
알고 있듯이 열 포인터의 벡터를 과도하게 할당하기 때문에 참조로 열 을 추가하고 삭제할 수 있습니다 . 계획은 행과 비슷한 작업을 수행하고 빠른 insert
및을 허용하는 것 delete
입니다. memmove
C에서 행 삭제를 사용 하면 삭제 된 행 다음에 항목 (각 열마다)을 버립니다. 테이블 중간에서 행을 삭제하면 SQL과 같은 행 저장소 데이터베이스와 비교할 때 여전히 비효율적입니다.이 행은 테이블에서 행을 빠르게 삽입하고 삭제하는 데 더 적합합니다. 그러나 여전히 행을 삭제하지 않고 새로운 큰 개체를 복사하는 것보다 훨씬 빠릅니다.
반면에 열 벡터가 과도하게 할당 되므로 끝에 행이 즉시 삽입 (삭제) 될 수 있습니다 . 예를 들어, 증가하는 시계열.
문제로 제기되었습니다 : 참조로 행 삭제 .
메모리 사용을 내부 삭제와 유사하게하기 위해 취한 접근법은 한 번에 열을 하위 집합으로 만들고 삭제하는 것입니다. 적절한 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
}
다음은 @ 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
>
추신. SO를 처음 사용했기 때문에 @ vc273의 스레드에 주석을 추가 할 수 없습니다 :-(
대신 NULL로 설정하거나 NA로 설정해보십시오 (첫 번째 열의 NA 유형과 일치)
set(DT,1:2, 1:3 ,NA_character_)
이 주제는 여전히 많은 사람들에게 흥미 롭습니다 (포함).
What about that? I used assign
to replace the glovalenv
and the code described previously. It would be better to capture the original environment but at least in globalenv
it is memory efficient and acts like a change by ref.
delete <- function(DT, del.idxs)
{
varname = deparse(substitute(DT))
keep.idxs <- setdiff(DT[, .I], del.idxs)
cols = names(DT);
DT.subset <- data.table(DT[[1]][keep.idxs])
setnames(DT.subset, cols[1])
for (col in cols[2:length(cols)])
{
DT.subset[, (col) := DT[[col]][keep.idxs]]
DT[, (col) := NULL]; # delete
}
assign(varname, DT.subset, envir = globalenv())
return(invisible())
}
DT = data.table(x = rep(c("a", "b", "c"), each = 3), y = c(1, 3, 6), v = 1:9)
delete(DT, 3)
Here are some strategies I have used. I believe a .ROW function may be coming. None of these approaches below are fast. These are some strategies a little beyond subsets or filtering. I tried to think like dba just trying to clean up data. As noted above, you can select or remove rows in 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
Note: .SD creates a subset of the original data and allows you to do quite a bit of work in j or subsequent data.table. See https://stackoverflow.com/a/47406952/305675. Here I ordered my irises by Sepal Length, take a specified Sepal.Length as minimum,select the top three (by Sepal Length) of all Species and return all accompanying data:
iris[order(-Sepal.Length)][Sepal.Length > 3,.SD[1:3],by=,.(Species)]
The approaches above all reorder a data.table sequentially when removing rows. You can transpose a data.table and remove or replace the old rows which are now transposed columns. When using ':=NULL' to remove a transposed row, the subsequent column name is removed as well:
m_iris <- data.table(t(iris))[,V3:=NULL] # V3 column removed
d_iris <- data.table(t(iris))[,V3:=V2] # V3 column replaced with V2
When you transpose the data.frame back to a data.table, you may want to rename from the original data.table and restore class attributes in the case of deletion. Applying ":=NULL" to a now transposed data.table creates all character classes.
m_iris <- data.table(t(d_iris));
setnames(d_iris,names(iris))
d_iris <- data.table(t(m_iris));
setnames(m_iris,names(iris))
You may just want to remove duplicate rows which you can do with or without a 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)),]
It is also possible to add an incremental counter with '.I'. You can then search for duplicated keys or fields and remove them by removing the record with the counter. This is computationally expensive, but has some advantages since you can print the lines to be removed.
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.
You can also just fill a row with 0s or NAs and then use an i query to delete them:
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),]
참고URL : https://stackoverflow.com/questions/10790204/how-to-delete-a-row-by-reference-in-data-table
'IT' 카테고리의 다른 글
내 앱을 성공적으로 제출 한 후“너무 많은 심볼 파일” (0) | 2020.06.18 |
---|---|
DIV가 전체 테이블 셀을 채우도록하십시오. (0) | 2020.06.18 |
Xcode 6-Ad-Hoc 배포를 위해 서명 인증서 / 프로비저닝 프로파일을 선택하는 방법은 무엇입니까? (0) | 2020.06.18 |
노드 및 오류 : EMFILE, 너무 많은 열린 파일 (0) | 2020.06.18 |
NoSQL 사용 사례 [폐쇄] (0) | 2020.06.18 |