Я новичок в R, поэтому, пожалуйста, будьте терпеливы. Я работаю с файлом CSV, который изначально состоял из 95 строк и более 10 000 столбцов. Первое, что мне нужно было сделать, это удалить все строки с суммой менее 1000. Я смог это сделать и сократил их до 80 строк, но когда я попытался адаптировать код к своим столбцам, это не сработало.
Мне нужно удалить любой столбец с суммой 0. У столбцов есть заголовки. Я пробовал несколько разных методов, но безуспешно.
Файл настроен так
A1 A2 A3 A4 A5 A6
Sample 1 394 28 1839 0 2389 24
Sample 2 4825 0 230 0 239 8349
Sample 3 439 329 932 0 948 348
Sample 4 239 832 3094 0 389 438
Sample 5 2389 13 390 0 5893 3849
Sample 6 98 320 23 0 9340 432
Это библиотеки, которые я использовал. Я использовал vroom
вместо readr
из-за размера моего файла.
library(vroom)
library(dplyr)
library(tidyverse)
Я пытаюсь удалить все столбцы с суммой 0, например A4. Сначала я попытался адаптировать код, который использовал для строк:
df <- vroom("file.csv")
keep <- colSums(df[sapply(df, is.numeric)][,]) > 0
df2 <- df[keep,]
Однако похоже, что Keep может работать только со значениями/строками x? Получал сообщение об ошибке, в котором говорилось, что значение Keep должно быть от 1 до 80, что соответствует количеству строк в файле. Буду признателен, если кто-нибудь сможет подтвердить/опровергнуть эту теорию.
Поскольку это не сработало, я попытался использовать which
, чтобы выбрать столбцы с нулевой суммой, чтобы можно было избавиться от них вручную.
unique.cols <- which(colSums(df[sapply(df, is.numeric)]) == 0)
Он выбрал все столбцы, а это не то, что мне нужно, и я до сих пор не понимаю, почему. Я пробовал поэкспериментировать с другими методами, такими как пакет janitor и функция Remove_empty, но они тоже не сработали. Я также пытался использовать макрос в Excel, но мой компьютер сломался, а затем больше не открывался...
Я нашел этот код, отвечая на другие вопросы в Stack, которые показались мне похожими на мои, но он полностью уничтожил мой набор данных и удалил гораздо больше столбцов, чем следовало бы. Из 10000+ осталось всего 300. Лишь несколько столбцов пусты.
df <- Filter(function(x)!all(is.na(x) || is.null(x) || x == "" || x == 0), df)
Вот пример того, что я получаю, когда использую функцию str(df)
.
str(df)
tibble [80 × 10,932] (S3: tbl_df/tbl/data.frame)
$ ...1 : chr [1:80] "sample 1" "sample 2" "sample 3" "sample 4" ...
$ A1 : num [1:80] 394 4825 439 239 2389 ...
$ A2 : num [1:80] 28 0 329 832 13 320 ...
$ A3 : num [1:80] 1839 230 932 3094 390 ...
Любой совет будет принят во внимание. Спасибо!
Это должно работать (по крайней мере, это работает в приведенном вами примере...)
num_cols <- sapply(df, is.numeric)
## easiest (may be not the most efficient) to split the data
## into num vs non-numeric columns
df_num <- df[num_cols]
## using != rather than > because you stated "is not equal to"
## rather than "greater than or equal to ..."
keep <- colSums(df_num) != 0
df_num <- df_num[, keep]
df2 <- cbind(df[!num_cols], df_num)
Давайте посмотрим на вашу первую попытку:
keep <- colSums(df[sapply(df, is.numeric)][,]) > 0
df2 <- df[keep,]
[, keep]
(сохранить столбцы), а не [keep, ]
(сохранить строки)...sapply(df, is.numeric)
кажется избыточным, если в вашем наборе данных есть только числовые столбцы (он будет TRUE
для каждого столбца); если предположить, что значения Sample xx
в вашем примере должны быть именами строк, это справедливо и для вашего набора данных.[,]
; Я не могу понять, что это должно делать...colSums
: с этой частью все в порядкеВ tidyverse это должно работать:
df |> select(where(\(x) !is.numeric(x) || sum(x) != 0))
(это может быть немного менее эффективно, потому что вычисление суммы по одному столбцу за раз может быть медленнее, чем использование colSums()
...)
под «заголовками» вы имеете в виду, что у вас есть первый столбец (например), который не является числом?
Да, мой первый столбец и первая строка нечисловые.
как ваша первая строка может быть нечисловой? Можете ли вы отредактировать свой вопрос, включив в него результаты str()
или summary()
, примененные к вашему фрейму данных?
Извините, вы правы. Я просматривал файл в Excel и забыл, что он не включает первую строку в фактическую часть кадра данных/имеет ее в качестве правильного заголовка. Я отредактировал вопрос, включив в него результаты str().
Используя Filter(), мы выбираем нечисловые столбцы и числовые столбцы с ненулевой суммой.
Filter(\(x) !is.numeric(x) || sum(x) != 0, df)
# A1 A2 A3 A5 A6
# Sample 1 394 28 1839 2389 24
# Sample 2 4825 0 230 239 8349
# Sample 3 439 329 932 948 348
# Sample 4 239 832 3094 389 438
# Sample 5 2389 13 390 5893 3849
# Sample 6 98 320 23 9340 432
Где
df <- data.frame(
A1 = c(394L, 4825L, 439L, 239L, 2389L, 98L),
A2 = c(28L, 0L, 329L, 832L, 13L, 320L),
A3 = c(1839L, 230L, 932L, 3094L, 390L, 23L),
A4 = integer(6),
A5 = c(2389L, 239L, 948L, 389L, 5893L, 9340L),
A6 = c(24L, 8349L, 348L, 438L, 3849L, 432L),
row.names = c("Sample 1", "Sample 2", "Sample 3", "Sample 4", "Sample 5", "Sample 6")
)
Спасибо за ответ! Совсем забыл про то, как работает индексация с Keep, спасибо! Однако теперь код выдает эту ошибку, и я снова не знаю, почему:
Logical subscript
keep` должен иметь размер 1 или 10932, а не 10931. Запуститеrlang::last_trace()
, чтобы увидеть, где произошла ошибка.` Код, который я использую:keep <- colSums(HHasvTable2[sapply(HHasvTable2, is.numeric)]) > 0 HHasvTable3 <- HHasvTable2[, keep]
Код пытается включить мои заголовки, а затем выдает ошибку, потому что не все числовые, если я не использую sapply. [,] — это остаток и излишек, да. Спасибо!