Как удалить пустые столбцы/столбцы с нулевой суммой

Я новичок в 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 ...

Любой совет будет принят во внимание. Спасибо!

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
80
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Это должно работать (по крайней мере, это работает в приведенном вами примере...)

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() ...)

Спасибо за ответ! Совсем забыл про то, как работает индексация с Keep, спасибо! Однако теперь код выдает эту ошибку, и я снова не знаю, почему: Logical subscript keep` должен иметь размер 1 или 10932, а не 10931. Запустите rlang::last_trace(), чтобы увидеть, где произошла ошибка.` Код, который я использую: keep <- colSums(HHasvTable2[sapply(HHasvTable2, is.numeric)]) > 0 HHasvTable3 <- HHasvTable2[, keep] Код пытается включить мои заголовки, а затем выдает ошибку, потому что не все числовые, если я не использую sapply. [,] — это остаток и излишек, да. Спасибо!

Jay 04.05.2024 01:19

под «заголовками» вы имеете в виду, что у вас есть первый столбец (например), который не является числом?

Ben Bolker 04.05.2024 16:54

Да, мой первый столбец и первая строка нечисловые.

Jay 06.05.2024 21:46

как ваша первая строка может быть нечисловой? Можете ли вы отредактировать свой вопрос, включив в него результаты str() или summary(), примененные к вашему фрейму данных?

Ben Bolker 06.05.2024 21:48

Извините, вы правы. Я просматривал файл в Excel и забыл, что он не включает первую строку в фактическую часть кадра данных/имеет ее в качестве правильного заголовка. Я отредактировал вопрос, включив в него результаты str().

Jay 06.05.2024 22:17
Ответ принят как подходящий

Используя 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")
)

Другие вопросы по теме