Помимо этих выше ответов, я хотел бы добавить несколько функций:
public static int parseIntOrDefault(String value, int defaultValue) {
int result = defaultValue;
try {
result = Integer.parseInt(value);
} catch (Exception e) {
}
return result;
}
public static int parseIntOrDefault(String value, int beginIndex, int defaultValue) {
int result = defaultValue;
try {
String stringValue = value.substring(beginIndex);
result = Integer.parseInt(stringValue);
} catch (Exception e) {
}
return result;
}
public static int parseIntOrDefault(String value, int beginIndex, int endIndex, int defaultValue) {
int result = defaultValue;
try {
String stringValue = value.substring(beginIndex, endIndex);
result = Integer.parseInt(stringValue);
} catch (Exception e) {
}
return result;
}
И вот результаты при их запуске:
public static void main(String[] args) {
System.out.println(parseIntOrDefault("123", 0)); // 123
System.out.println(parseIntOrDefault("aaa", 0)); // 0
System.out.println(parseIntOrDefault("aaa456", 3, 0)); // 456
System.out.println(parseIntOrDefault("aaa789bbb", 3, 6, 0)); // 789
}
Вы должны использовать либо индексирование, либо функцию 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
Сначала вы можете использовать прямую индексацию (с булевыми векторами) вместо повторного доступа к именам столбцов, если вы работаете с одним и тем же фреймом данных; это будет безопаснее, как указано Истой, и быстрее писать и исполнять. Так что вам нужно только:
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.
Наконец вы можете использовать подмножество (), но оно не может быть действительно использовано в коде (даже помощь файл предупреждает об этом). В частности, проблема в том, что если вы хотите напрямую использовать функцию drop для susbset (), вам нужно написать без кавычек выражение, соответствующее именам столбцов:
subset( data, select = -c("iden", "name", "x_serv", "m_serv") ) # WILL NOT WORK
subset( data, select = -c(iden, name, x_serv, m_serv) ) # WILL
Как bonus , здесь приведен малый критерий для разных опций, который ясно показывает, что подмножество является более медленным, и что первый, переназначающий метод быстрее:
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
[/g5]
Код ниже:
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)
Я изменил код на:
# 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]
В любом случае, ответ Джубы - лучшее решение моей проблемы!
Я не могу ответить на ваш вопрос в комментариях из-за низкой оценки репутации.
Следующий код даст вам ошибку, потому что функция вставки возвращает символьную строку
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
}
Не используйте -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()
!
Вот быстрое решение для этого. Скажем, у вас есть кадр данных X с тремя столбцами A, B и C:
> 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 для colnames, чтобы получить индекс столбца, который вы можете использовать, чтобы опустить столбец.
> 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
EDIT: 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
Вот еще одно решение, которое может быть полезным для других. Приведенный ниже код выбирает небольшое количество строк и столбцов из большого набора данных. Столбцы выбираются как в одном из ответов Джубы, за исключением того, что я использую функцию вставки, чтобы выбрать набор столбцов с именами, которые нумеруются последовательно:
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
Я попытался удалить столбец при использовании пакета 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. Вы были предупреждены!
Вы также можете попробовать пакет 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