데이터 프레임에서 이름별로 열을 삭제하는 방법
대용량 데이터 세트가 있는데 특정 열을 읽거나 다른 열을 모두 삭제하려고 합니다.
data <- read.dta("file.dta")
관심 없는 열을 선택합니다.
var.out <- names(data)[!names(data) %in% c("iden", "name", "x_serv", "m_serv")]
그리고 다음과 같은 것을 하고 싶습니다.
for(i in 1:length(var.out)) {
paste("data$", var.out[i], sep="") <- NULL
}
모든 원하지 않는 열을 삭제합니다.이것이 최적의 해결책입니까?
인덱싱 또는 다음 중 하나를 사용해야 합니다.subset
기능.예:
R> df <- data.frame(x=1:5, y=2:6, z=3:7, u=4:8)
R> df
x y z u
1 1 2 3 4
2 2 3 4 5
3 3 4 5 6
4 4 5 6 7
5 5 6 7 8
그러면 다음을 사용할 수 있습니다.which
기능 및-
열 인덱스의 연산자:
R> df[ , -which(names(df) %in% c("z","u"))]
x y
1 1 2
2 2 3
3 3 4
4 4 5
5 5 6
또는, 훨씬 더 단순하게,select
의 주장subset
함수: 그런 다음 사용할 수 있습니다.-
열 이름의 벡터에서 연산자를 직접 사용할 수 있으며 이름 주위의 따옴표를 생략할 수도 있습니다!
R> subset(df, select=-c(z,u))
x y
1 1 2
2 2 3
3 3 4
4 4 5
5 5 6
다른 열을 놓는 대신 원하는 열을 선택할 수도 있습니다.
R> df[ , c("x","y")]
x y
1 1 2
2 2 3
3 3 4
4 4 5
5 5 6
R> subset(df, select=c(x,y))
x y
1 1 2
2 2 3
3 3 4
4 4 5
5 5 6
사용 안 함-which()
이것 때문에, 그것은 매우 위험합니다.고려 사항:
dat <- data.frame(x=1:5, y=2:6, z=3:7, u=4:8)
dat[ , -which(names(dat) %in% c("z","u"))] ## works as expected
dat[ , -which(names(dat) %in% c("foo","bar"))] ## deletes all columns! Probably not what you wanted...
대신 부분 집합 또는!
함수:
dat[ , !names(dat) %in% c("z","u")] ## works as expected
dat[ , !names(dat) %in% c("foo","bar")] ## returns the un-altered data.frame. Probably what you want
저는 고통스러운 경험을 통해 이것을 배웠습니다.과도하게 사용하지 말 것which()
!
첫째, 동일한 데이터 프레임으로 작업하는 경우 열 이름에 다시 액세스하는 대신 직접 인덱싱(불리언 벡터 사용)을 사용할 수 있습니다. Ista가 지적한 대로 더 안전하고 쓰기 및 실행 속도가 빨라집니다.따라서 필요한 것은 다음과 같습니다.
var.out.bool <- !names(data) %in% c("iden", "name", "x_serv", "m_serv")
데이터를 재할당하기만 하면 됩니다.
data <- data[,var.out.bool] # or...
data <- data[,var.out.bool, drop = FALSE] # You will need this option to avoid the conversion to an atomic vector if there is only one column left
둘째, 쓰기가 더 빠르며 제거할 열에 NULL을 직접 할당할 수 있습니다.
data[c("iden", "name", "x_serv", "m_serv")] <- list(NULL) # You need list() to respect the target structure.
마지막으로 하위 집합()을 사용할 수 있지만 코드에서 실제로 사용할 수는 없습니다(도움말 파일에서 경고가 표시되기도 함)특히, subset()의 드롭 기능을 직접 사용하려면 열 이름에 해당하는 식을 따옴표 없이 써야 한다는 것이 문제입니다.
subset( data, select = -c("iden", "name", "x_serv", "m_serv") ) # WILL NOT WORK
subset( data, select = -c(iden, name, x_serv, m_serv) ) # WILL
추가적으로, 다양한 옵션에 대한 작은 벤치마크는 하위 집합이 더 느리고 첫 번째 재할당 방법이 더 빠르다는 것을 분명히 보여줍니다.
re_assign(dtest, drop_vec) 46.719 52.5655 54.6460 59.0400 1347.331
null_assign(dtest, drop_vec) 74.593 83.0585 86.2025 94.0035 1476.150
subset(dtest, select = !names(dtest) %in% drop_vec) 106.280 115.4810 120.3435 131.4665 65133.780
subset(dtest, select = names(dtest)[!names(dtest) %in% drop_vec]) 108.611 119.4830 124.0865 135.4270 1599.577
subset(dtest, select = -c(x, y)) 102.026 111.2680 115.7035 126.2320 1484.174
코드는 다음과 같습니다.
dtest <- data.frame(x=1:5, y=2:6, z = 3:7)
drop_vec <- c("x", "y")
null_assign <- function(df, names) {
df[names] <- list(NULL)
df
}
re_assign <- function(df, drop) {
df <- df [, ! names(df) %in% drop, drop = FALSE]
df
}
res <- microbenchmark(
re_assign(dtest,drop_vec),
null_assign(dtest,drop_vec),
subset(dtest, select = ! names(dtest) %in% drop_vec),
subset(dtest, select = names(dtest)[! names(dtest) %in% drop_vec]),
subset(dtest, select = -c(x, y) ),
times=5000)
plt <- ggplot2::qplot(y=time, data=res[res$time < 1000000,], colour=expr)
plt <- plt + ggplot2::scale_y_log10() +
ggplot2::labs(colour = "expression") +
ggplot2::scale_color_discrete(labels = c("re_assign", "null_assign", "subset_bool", "subset_names", "subset_drop")) +
ggplot2::theme_bw(base_size=16)
print(plt)
사용해 볼 수도 있습니다.dplyr
패키지:
R> df <- data.frame(x=1:5, y=2:6, z=3:7, u=4:8)
R> df
x y z u
1 1 2 3 4
2 2 3 4 5
3 3 4 5 6
4 4 5 6 7
5 5 6 7 8
R> library(dplyr)
R> dplyr::select(df2, -c(x, y)) # remove columns x and y
z u
1 3 4
2 4 5
3 5 6
4 6 7
5 7 8
이에 대한 빠른 해결책이 있습니다.예를 들어, 열이 A, B, C인 데이터 프레임 X가 있다고 가정합니다.
> X<-data.frame(A=c(1,2),B=c(3,4),C=c(5,6))
> X
A B C
1 1 3 5
2 2 4 6
열을 제거하려는 경우(예: B), 열 이름에 grep을 사용하여 열 인덱스를 가져오면 열을 생략할 수 있습니다.
> X<-X[,-grep("B",colnames(X))]
새 X 데이터 프레임은 다음과 같습니다(이번에는 B 열이 없습니다).
> X
A C
1 1 5
2 2 6
grep의 장점은 정규식과 일치하는 열을 여러 개 지정할 수 있다는 점입니다.X에 다섯 개의 열(A, B, C, D, E)이 있는 경우:
> X<-data.frame(A=c(1,2),B=c(3,4),C=c(5,6),D=c(7,8),E=c(9,10))
> X
A B C D E
1 1 3 5 7 9
2 2 4 6 8 10
열 B 및 D를 꺼냅니다.
> X<-X[,-grep("B|D",colnames(X))]
> X
A C E
1 1 5 9
2 2 6 10
편집: Matthew Lundberg가 아래 댓글에서 제안한 grepl을 고려합니다.
> X<-data.frame(A=c(1,2),B=c(3,4),C=c(5,6),D=c(7,8),E=c(9,10))
> X
A B C D E
1 1 3 5 7 9
2 2 4 6 8 10
> X<-X[,!grepl("B|D",colnames(X))]
> X
A C E
1 1 5 9
2 2 6 10
존재하지 않는 열을 삭제하려고 하면 아무 일도 일어나지 않습니다.
> X<-X[,!grepl("G",colnames(X))]
> X
A C E
1 1 5 9
2 2 6 10
df2 <- df[!names(df) %in% c("c1", "c2")]
는 패키지를 사용하는 동안 열을 삭제하려고 .data.table
예상치 못한 결과를 얻었습니다.저는 다음과 같은 것들이 게시할 가치가 있다고 생각합니다.주의사항을 말씀드리겠습니다.
[ 매튜 편집...]
DF = read.table(text = "
fruit state grade y1980 y1990 y2000
apples Ohio aa 500 100 55
apples Ohio bb 0 0 44
apples Ohio cc 700 0 33
apples Ohio dd 300 50 66
", sep = "", header = TRUE, stringsAsFactors = FALSE)
DF[ , !names(DF) %in% c("grade")] # all columns other than 'grade'
fruit state y1980 y1990 y2000
1 apples Ohio 500 100 55
2 apples Ohio 0 0 44
3 apples Ohio 700 0 33
4 apples Ohio 300 50 66
library('data.table')
DT = as.data.table(DF)
DT[ , !names(dat4) %in% c("grade")] # not expected !! not the same as DF !!
[1] TRUE TRUE FALSE TRUE TRUE TRUE
DT[ , !names(DT) %in% c("grade"), with=FALSE] # that's better
fruit state y1980 y1990 y2000
1: apples Ohio 500 100 55
2: apples Ohio 0 0 44
3: apples Ohio 700 0 33
4: apples Ohio 300 50 66
기본적으로 다음에 대한 구문입니다.data.table
와 정확히 동일하지 않습니다.data.frame
사실 많은 차이가 있습니다. FAQ 1.1과 FAQ 2.17을 참조하십시오.경고를 받았습니다!
코드를 다음으로 변경했습니다.
# read data
dat<-read.dta("file.dta")
# vars to delete
var.in<-c("iden", "name", "x_serv", "m_serv")
# what I'm keeping
var.out<-setdiff(names(dat),var.in)
# keep only the ones I want
dat <- dat[var.out]
어쨌든, 주바의 대답은 내 문제에 대한 최고의 해결책입니다!
원래 데이터 프레임의 "df" 열 이름을 정확히 알고 있는 경우:
cols_to_drop <- c("A", "B", "C")
df_clean = df[,!(names(df) %in% cols_to_drop)]
Src: https://www.listendata.com/2015/06/r-keep-drop-columns-from-data-frame.html
여기 다른 사람들에게 도움이 될 수 있는 또 다른 해결책이 있습니다.아래 코드는 큰 데이터 집합에서 소수의 행과 열을 선택합니다.열은 붙여넣기 기능을 사용하여 순차적으로 번호가 지정된 이름의 열 집합을 선택하는 것을 제외하고 juba의 답변 중 하나로 선택됩니다.
df = read.table(text = "
state county city region mmatrix X1 X2 X3 A1 A2 A3 B1 B2 B3 C1 C2 C3
1 1 1 1 111010 1 0 0 2 20 200 4 8 12 NA NA NA
1 2 1 1 111010 1 0 0 4 NA 400 5 9 NA NA NA NA
1 1 2 1 111010 1 0 0 6 60 NA NA 10 14 NA NA NA
1 2 2 1 111010 1 0 0 NA 80 800 7 11 15 NA NA NA
1 1 3 2 111010 0 1 0 1 2 1 2 2 2 10 20 30
1 2 3 2 111010 0 1 0 2 NA 1 2 2 NA 40 50 NA
1 1 4 2 111010 0 1 0 1 1 NA NA 2 2 70 80 90
1 2 4 2 111010 0 1 0 NA 2 1 2 2 10 100 110 120
1 1 1 3 010010 0 0 1 10 20 10 200 200 200 1 2 3
1 2 1 3 001000 0 0 1 20 NA 10 200 200 200 4 5 9
1 1 2 3 101000 0 0 1 10 10 NA 200 200 200 7 8 NA
1 2 2 3 011010 0 0 1 NA 20 10 200 200 200 10 11 12
", sep = "", header = TRUE, stringsAsFactors = FALSE)
df
df2 <- df[df$region == 2, names(df) %in% c(paste("C", seq_along(1:3), sep=''))]
df2
# C1 C2 C3
# 5 10 20 30
# 6 40 50 NA
# 7 70 80 90
# 8 100 110 120
저는 낮은 평판 점수 때문에 당신의 질문에 답변할 수 없습니다.
붙여넣기 함수가 문자열을 반환하므로 다음 코드는 오류를 제공합니다.
for(i in 1:length(var.out)) {
paste("data$", var.out[i], sep="") <- NULL
}
가능한 해결책은 다음과 같습니다.
for(i in 1:length(var.out)) {
text_to_source <- paste0 ("data$", var.out[i], "<- NULL") # Write a line of your
# code like a character string
eval (parse (text=text_to_source)) # Source a text that contains a code
}
아니면 그냥 하세요:
for(i in 1:length(var.out)) {
data[var.out[i]] <- NULL
}
df = mtcars
remove vs and am because they are categorical. In the dataset vs is in column number 8, am is in column number 9
dfnum = df[,-c(8,9)]
언급URL : https://stackoverflow.com/questions/5234117/how-to-drop-columns-by-name-in-a-data-frame
'programing' 카테고리의 다른 글
dplyr을 사용하여 테이블의 모든 행에 함수를 적용하시겠습니까? (0) | 2023.06.22 |
---|---|
VSCode의 현재 변경 사항을 한 번에 모두 수용하려면 어떻게 해야 합니까? (0) | 2023.06.22 |
Firebase Analytics setScreenName이(가) 더 이상 사용되지 않습니다. (0) | 2023.06.21 |
도커 mariadb에서 연합 엔진을 활성화하는 방법 (0) | 2023.06.21 |
인스턴트 기사 - 트윗 포함 (0) | 2023.06.21 |