sum () или другой метод для подсчета ИСТИНЫ в подмножестве кадра данных - PullRequest
0 голосов
/ 29 апреля 2019

У меня есть 5000 x 8000 фреймов данных в основном логических значений.Я хотел бы посчитать ИСТИННЫЕ значения в различных прямоугольных частях.Идеальное решение выглядело бы так:

features.total <- sum(df[ , 651:8500])

Увы, это не работает.Вот несколько примеров, с которыми можно поиграть:

aa <- bb <- cc <- dd <- rep.int(FALSE,4)
df1 <- data.frame(aa, bb, cc, dd, stringsAsFactors = FALSE)
df1[2:3,2:3] <- TRUE

ww <- xx <- yy <- zz <- rep.int(0,4)
df2 <- data.frame(ww, xx, yy, zz, stringsAsFactors = FALSE)
df2[2:3,2:3] <- 1

v0 <- c(FALSE, TRUE, TRUE, TRUE)
v1 <- as.vector(df1[2, ])
v2 <- c(0, 1, 1, 0)

sum () прекрасно работает с теми, которые вы ожидаете, но не работает с другими:

Ошибка в FUN (X [[i]], ...): определено только для фрейма данных со всеми числовыми переменными

  • sum(v0) отлично работает
  • sum(v1) не удается
  • sum(v2) отлично работает
  • sum(df1) не удается
  • sum(df2) отлично работает

Логические объекты меньше и проще.Есть ли альтернативный подход, который позволил бы мне придерживаться ИСТИНА и ЛОЖЬ, но удовлетворить необходимость добавления регионов?

Ответы [ 2 ]

1 голос
/ 29 апреля 2019

Вместо того, чтобы вручную распечатывать и преобразовывать в matrix, как предложил Джей, мы также можем использовать некоторые R-функции, специально предназначенные для работы с data.frames, например, rowSums() и colSums().Эти функции работают с каждой строкой / столбцом data.frame, поэтому неявно преобразуют свои аргументы в векторы, для которых определена сумма.После того, как это сделано для каждой строки / столбца, мы можем просто суммировать результат, чтобы получить общую сумму.

aa <- bb <- cc <- dd <- rep.int(FALSE,4)
df1 <- data.frame(aa, bb, cc, dd, stringsAsFactors = FALSE)
df1[2:3,2:3] <- TRUE

ww <- xx <- yy <- zz <- rep.int(0,4)
df2 <- data.frame(ww, xx, yy, zz, stringsAsFactors = FALSE)
df2[2:3,2:3] <- 1

v0 <- c(FALSE, TRUE, TRUE, TRUE)
v1 <- as.vector(df1[2, ])
v2 <- c(0, 1, 1, 0)

######### working code

> sum(colSums(v1))
[1] 2

> sum(colSums(df1))
[1] 4
0 голосов
/ 29 апреля 2019

sum определяется только для фрейма данных со всеми числовыми переменными.Если мы посмотрим на шаблоны, то увидим, что sum терпит неудачу, data.frame s, то есть перечисленные логические объекты ($).

str(v0) # works fine
# logi [1:4] FALSE TRUE TRUE TRUE

# compare:
str(as.data.frame(v0))
# 'data.frame': 4 obs. of  1 variable:
#  $ v0: logi  FALSE TRUE TRUE TRUE

str(v1) # fails
# 'data.frame': 1 obs. of  4 variables:
# $ aa: logi FALSE
# $ bb: logi TRUE
# $ cc: logi TRUE
# $ dd: logi FALSE

str(v2) # works fine
# num [1:4] 0 1 1 0

str(df1) # fails
# 'data.frame': 4 obs. of  4 variables:
# $ aa: logi  FALSE FALSE FALSE FALSE
# $ bb: logi  FALSE TRUE TRUE FALSE
# $ cc: logi  FALSE TRUE TRUE FALSE
# $ dd: logi  FALSE FALSE FALSE FALSE

str(df2) # works fine
# 'data.frame': 4 obs. of  4 variables:
# $ ww: num  0 0 0 0
# $ xx: num  0 1 1 0
# $ yy: num  0 1 1 0
# $ zz: num  0 0 0 0

Когда мы unlist их, все работает нормально.

str(v1) # fails
sum(unlist(v1)) # works fine
# [1] 2

str(df1) # fails
sum(unlist(df1)) # works fine
# [1] 4

Вместо unlist мы также можем преобразовать data.frame s as.matrix до sum, просто избавиться от структуры списка.

sum(as.matrix(v1))
# [1] 2
sum(as.matrix(df1))
# [1] 4

Или дажекороче ...

sum(t(t(v1)))
# [1] 2
sum(t(t(df1)))
# [1] 4

...

sum(!(v1))
# [1] 2

sum(!!(df1))
# [1] 4

Редактировать

Применять на data.frame с такими

df1
#   a b    l1   l2    l3
# 1 t z  TRUE TRUE  TRUE
# 2 b a FALSE TRUE  TRUE
# 3 h j FALSE TRUE FALSE
# 4 c x  TRUE TRUE  TRUE

str(df1)
# 'data.frame': 4 obs. of  5 variables:
#  $ a : Factor w/ 4 levels "b","d","e","x": 3 2 1 4
#  $ b : Factor w/ 4 levels "c","r","w","x": 2 1 4 3
#  $ l1: logi  FALSE FALSE TRUE TRUE
#  $ l2: logi  TRUE TRUE TRUE TRUE
#  $ l3: logi  FALSE TRUE FALSE TRUE

мы могли бы sum вверх по прямоугольникам, вот так

sum(!!df1[3:5])
sum(!!df1[sapply(df1, is.logical)])  # or, allocating logical columns automatically 
# [1] 8
sum(!!df1[3:4, 4:5])  # or, sub-rectangles
# [1] 3

Данные

df1 <- structure(list(a = structure(c(3L, 2L, 1L, 4L), .Label = c("b", 
"d", "e", "x"), class = "factor"), b = structure(c(2L, 1L, 4L, 
3L), .Label = c("c", "r", "w", "x"), class = "factor"), l1 = c(FALSE, 
FALSE, TRUE, TRUE), l2 = c(TRUE, TRUE, TRUE, TRUE), l3 = c(FALSE, 
TRUE, FALSE, TRUE)), class = "data.frame", row.names = c(NA, 
-4L))
...