Исключение столбцов из фрейма данных на основе сумм столбцов
Я работаю над набором данных, который включает данные сообщества, а многие из столбцов (видов) имеют множество нулей. Я хотел бы иметь возможность отбросить эти столбцы для некоторых анализов, которые я делаю, исходя из суммы всего столбца.
Я соблазн сделать это с помощью цикла for, но я слышал, что применение и функции лучше, когда вы используете R.
Моя цель - удалить все столбцы с суммой менее 15.
Я использовал which()
для удаления строк по факторам, например,
September<-which(data$Time_point=="September")
data<-data[-September,]
и два способа, которыми я попытался удалить столбцы, - это использовать apply()
:
data<-data[,apply(data,2,function(x)sum(x<=15))]
и с помощью коммисивного цикла /if else combo:
for (i in 6:length(data)){
if (sum(data[,i])<=15)
data[,i]<-NULL
else
data[,i]<-data[,i]
}
Ни один из этих методов не работает. Разумеется, есть элегантный способ избавиться от столбцов на основе логических критериев?
str(head(data,10))
'data.frame': 10 obs. of 23 variables:
$ Core_num : Factor w/ 159 levels "152","153","154",..: 133 72 70 75 89 85 86 90 95 99
$ Cage_num : num 0 1 2 3 4 5 6 7 8 9
$ Treatment : Factor w/ 4 levels "","C","CC","NC": 1 2 2 2 2 2 2 2 2 2
$ Site : Factor w/ 10 levels "","B","B07","B08",..: 1 8 8 8 7 7 7 7 9 9
$ Time_point : Factor w/ 3 levels "","May","September": 1 2 2 2 2 2 2 2 2 2
$ Spionidae : num 108 0 0 0 0 0 0 0 0 0
$ Syllidae : num 185 0 0 0 3 8 0 1 4 1
$ Opheliidae : num 424 0 1 0 0 0 1 1 0 0
$ Cossuridae : num 164 0 7 3 0 0 0 0 0 0
$ Sternaspidae: num 214 0 0 6 1 0 11 9 0 0
$ Sabellidae : num 1154 0 2 2 0 ...
$ Capitellidae: num 256 1 10 17 0 3 0 0 0 0
$ Dorvillidae : num 21 1 0 0 0 0 0 0 0 0
$ Cirratulidae: num 17 0 0 0 0 0 0 0 0 0
$ Oligochaeta : num 3747 12 41 27 32 ...
$ Nematoda : num 410 5 4 13 0 0 0 2 2 0
$ Sipuncula : num 33 0 0 0 0 0 0 0 0 0
$ Ostracoda : num 335 0 1 0 0 0 0 0 0 0
$ Decapoda : num 62 0 4 0 1 0 0 0 0 0
$ Amphipoda : num 2789 75 17 34 89 ...
$ Copepoda : num 75 0 0 0 0 0 0 0 0 0
$ Tanaidacea : num 84 0 0 0 1 0 0 0 0 0
$ Mollusca : int 55 0 4 0 0 0 0 0 0 0
Ответы
Ответ 1
Как насчет простого подмножества? Во-первых, мы создаем простую структуру данныхL
R> dd = data.frame(x = runif(5), y = 20*runif(5), z=20*runif(5))
Затем выберите столбцы, где сумма больше 15
R> dd1 = dd[,colSums(dd) > 15]
R> ncol(dd1)
[1] 2
В вашем наборе данных вы хотите только подмножество столбцов 6, поэтому что-то вроде:
##Drop the first five columns
dd[,colSums(dd[,6:ncol(dd)]) > 15]
или
#Keep the first six columns
cols_to_drop = c(rep(TRUE, 5), dd[,6:ncol(dd)]>15)
dd[,cols_to_drop]
должен работать.
Ключевой частью, которую следует отметить, является то, что в квадратных скобках нам нужен вектор логических элементов, т.е. вектор TRUE и FALSE. Поэтому, если вы хотите подмножество, используя что-то более сложное, затем создайте функцию, которая возвращает TRUE или FALSE и подмножество, как обычно.
Ответ 2
Вы должны иметь возможность напрямую индексировать ваш data.frame с помощью boolean и colSums()
. Например:
set.seed(123)
dat <- data.frame(var1 = runif(10), var2 = rnorm(10), var3 = rlnorm(10))
colSums(dat)
#-----
var1 var2 var3
5.782475 1.317914 12.91987
#Let set the threshold at 5, so we should get var1 and var3
> dat[, colSums(dat) > 5]
#-----
var1 var3
1 0.2875775 5.9709924
2 0.7883051 1.6451811
3 0.4089769 0.1399294
...
EDIT - для адресации нечисловых столбцов
set.seed(123)
dat <- data.frame(var1 = runif(10), var2 = rnorm(10), var3 = rlnorm(10), var4 = "notNumeric")
require(plyr)
dat[, -which(numcolwise(sum)(dat) < 5)]
Consolec:/документы и настройки /charles/desktop/
> dat[, -which(numcolwise(sum)(dat) < 5)]
var1 var3 var4
1 0.2875775 5.9709924 notNumeric
2 0.7883051 1.6451811 notNumeric
3 0.4089769 0.1399294 notNumeric
.....
Ответ 3
Это приведет к возврату столбцов, которые не содержат всех нулей, включая коэффициенты и столбцы символов (я читаю только в первой строке chunky вашей информации):
Прочитайте некоторые из ваших данных:
dat <- read.table(text=" Core_num Cage_num Treatment Site Time_point Spionidae Nereididae Syllidae Opheliidae
6 24 1 C M2 May 0 0 0 0
4 22 2 C M2 May 0 0 0 1
9 27 3 C M2 May 0 0 0 0
23 41 4 C M May 0 0 3 0
19 37 5 C M May 0 0 8 0
20 38 6 C M May 0 0 0 1", header=T)
Код:
summer <- function(x){
if(is.numeric(x)){
sum(x) > 15
} else {
TRUE
}
}
dat[, sapply(dat, summer)]
Ответ 4
У меня просто была такая же проблема. Вот решение с использованием Tidyverse, если у вас есть как числовые, так и не числовые столбцы:
library(tidyverse)
set.seed(123)
dat <- data.frame(var1 = runif(10), var2 = rnorm(10), var3 = rlnorm(10), var4 = "notNumeric", var5 =0, var6 = FALSE )
dat %>%
select_if(negate(function(col) is.numeric(col) && sum(col) < 15))