Редактирование таблиц данных в R

Редактирование таблиц в R

В прошлый раз мы говорили о том, как загрузить данные в среду R. Следующим важным этапом является их подготовка к визуализации и статистическому анализу. Для этого нам, как правило, необходимо внести некоторые изменения в таблицу, например: удалить столбец или строку, переименовать колонку, произвести сортировку или фильтрацию данных. Многие из этих операций можно сделать в Excel. Однако, зачастую возникают ситуации, когда необходимо изменить структуру или содержание таблицы прямо в ходе анализа. И вот тут у начинающих пользователей R могут возникнуть проблемы. В этой статье мы научимся их решать.


Структура таблицы и изменение типов данных

Лучший способ для закрепления новых знаний - это практика. Поэтому мы продолжим работать с таблицей физических данных студентов одного из военных вузов "voenvuz". Итак, загрузим знакомую уже нам таблицу в Rgui (таблицу можно скачать здесь).

Функции head и str

Для того, чтобы посмотреть правильно ли загрузились данные, введем команду head(voenvuz), которая покажет первые 6 строчек нашей таблицы. Если все загрузилось нормально, то переходим к команде str(voenvuz), которая выведет в консоль структуру таблицы.

Функция str R

Итак, в поле "data.frame" мы видим, что наша таблица состоит из 20 строк и 6 столбцов. Под ним располагается список названий столбцов, тип данных и первые шесть элементов каждого столбца. Обратите внимание, что колонки "Name" и "Rhesus.factor" сейчас хранят в себе категориальный тип данных (Factor), а остальные - целочисленный. Компьютер вычислил это автоматически, но в нашем случае - вычислил неверно. Прежде чем мы исправим типы этих данных, немного теоретической информации.

О типах данных

Почему важно правильно распознать тип данных в столбцах таблицы? Потому что при проведении статистических тестов, информация о типе данных учитывается и влияет на результат.

В языке R можно выделить 5 основных типов данных, хранящихся в столбцах таблицы:

  • числовой (numeric);
  • целочисленный (integer);
  • текстовый (character);
  • категориальный (Factor);
  • логический (logical).

Есть также комплексный (complex) и сырой (raw) типы данных, но они редко встречаются, и поэтому я о них здесь писать не буду. Пропущенные данные обозначаются как "NA" (от англ. not available - недоступно), и тогда R игнорирует их.


Изменим типы данных на практике

Посмотрим еще раз на таблицу. Логично предположить, что столбец "Name" с именами студентов не содержит никаких категорий, поэтому, преобразуем эту колонку в обычный текстовый тип данных:

voenvuz$Name <- as.character(voenvuz$Name) 

Идем дальше, столбец "Age" был правильно идентифицирован как целочисленный. А вот столбцы "Height" и "Weight" являются скорее числовыми, т.к. могут содержать промежуточные значения, например 182.5. Переделаем их из типа Integer в тип Numeric:

voenvuz$Height <- as.numeric(voenvuz$Height) 
voenvuz$Weight <- as.numeric(voenvuz$Weight) 

Последнее, что нам нужно - это изменить тип данных в столбце "Blood.group". Каждый из студентов так или иначе имеет одну из 4 групп крови, соответственно, этот столбец содержит четыре категории: "1", "2", "3", "4". Другими словами, в нем должен находиться категориальный тип данных:

voenvuz$Blood.group <- as.factor(voenvuz$Blood.group)

В итоге, повторив команду str(voenvuz), мы должны получить вот такую картинку.

Меняем тип данных в R

Редактирование элементов таблицы

Иногда возникают ситуации, когда необходимо вставить в таблицу столбец или строку, изменить значение элемента или название колонки. Наша таблица - не исключение и нуждается в доработке.


Добавление строк

Добавим в таблицу данные о двух новых студентах: Иване и Олеге. Для этого необходимо создать новую структуру - список (list), В список мы по порядку вносим параметры, совпадающие со структурой таблицы (напомню, что в кавычках мы пишем нечисловые типы данных):

Ivan <- list("Ivan", 21, 175, 67, "2", "+")
Oleg <- list("Oleg", 24, 189, 82, "1", "+")

После, при помощи функции rbind (от англ. row bind, что дословно означает "связать строчки") мы объединим эти два списка с нашей таблицей:

voenvuz <- rbind(voenvuz, Ivan, Oleg)

Добавление столбцов

Теперь у нас в таблице два Ивана и два Олега. В данном случае хорошо было бы прописать для каждого студента свой идентификационный номер (ID), чтобы не запутаться, кто есть кто. Для этого создадим структуру, которая называется вектор (последовательность элементов одного типа). В него мы запишем последовательность от 1 до 22, так, чтобы у каждого из наших 22 студентов был свой уникальный ID:

ID <- c(1:22)

Теперь объединим наш вектор с таблицей, воспользовавшись функцией cbind (от англ. column bind):

voenvuz <- cbind(voenvuz, ID)

Не забудьте поменять тип данных нового столбца на символьный:

voenvuz$ID <- as.character(voenvuz$ID)

В качестве еще одного примера добавления новых столбцов с данными в таблицу, рассчитаем индекс массы тела (BMI) для каждого студента. Для этого, мы воспользуемся новым способом: напишем математическую формулу индекса на языке R и присвоим ей новое имя столбца "BMI" внутри нашей таблицы:

voenvuz$BMI <- voenvuz$Weight / (voenvuz$Height * 0.01)^2

Проверьте, что получилось, используя уже знакомые нам функции head и str


Удаление строк и столбцов

Существует относительно "универсальная формула" для удаления элементов таблицы: new.data <- my.data[ , ]
Для того, чтобы корректно ее использовать необходимо запомнить несколько правил:

  1. После имени таблицы пространство внутри квадратных скобок следует разделить на две части запятой.
  2. Все, что находится до запятой, относится к строчкам, все что после - к столбцам.
  3. Поставьте минус перед номером столбца или номером строки, которую собираетесь удалить.
  4. Если таких элементов несколько, используйте функцию c(...): внутри скобок перечисление элементов через запятую.

В нашем случае, удалять из таблицы ничего не надо, но я покажу пару примеров, назвав "укороченные" таблицы именами "trash1", "trash2", "trash3", "trash4":

trash1 <- voenvuz[ , -7]    # удалим раннее созданный столбец "ID"
trash2 <- voenvuz[ -2, ]    # удалим строку под номером 2 (данные Петра)
trash3 <- voenvuz[ -c(1,2,3,4,5,6,7,8,9,10), ]   # удалим первые десять строк
trash4 <- voenvuz[ -c(1:10), ]   # то же самое, только код короче

Изменение имен столбцов и  данных в ячейках:

Переименуем колонку "Rhesus.factor" на укороченное "Rhesus". Для этого нужно вызвать функцию names, написать в параметрах функции имя таблицы и номер столбца, и присвоить ему новое имя:

names(voenvuz)[6] <- "Rhesus"

Изменение данные в ячейках таблицы не представляет особой сложности. В квадратных скобках прописываем координаты нужной ячейки (до запятой - строка, после запятой - столбец) и присваиваем новое значение:

voenvuz[1, "Name"] <- "Vanya" 
Редактируем таблицу в R

После всех наших манипуляций мы должны получить вот такую таблицу данных:


Фильтрация и сортировка данных

В качестве примера, исключим из таблицы данных студентов, чей возраст больше 23 лет. Существует множество способов решения подобного рода задач, включая циклы if-else, for или while (о них будет написана отдельная статья). Однако в нашем случае хватит простого фильтра, основанного на логическом операторе "<=" (меньше или равно). В квадратных скобках таблицы находится объект таблицы, по которому будет проводиться фильтрация:

voenvuz.final <- voenvuz[voenvuz$Age <= 23, ]

Того же результата мы добьемся, если будем использовать логические операторы ">" (больше) и "!" (исключить):

voenvuz.final <- voenvuz[!voenvuz$Age > 23, ]

Итак, мы получили финальную версию таблицы "voenvuz.final". Осталось лишь упорядочить столбцы:

voenvuz.final <- voenvuz.final[,c("Name", "ID", "Age", "Height", "Weight", "BMI", "Blood.group", "Rhesus")]

И произвести сортировку данных по имени студентов, используя функцию order:

voenvuz.final <- voenvuz.final[order(voenvuz.final$Name),]
Результат обработки данных R

После завершения редактирования таблицы, обновим имена строк, т.к. сейчас они не соответствуют действительности, и выведем таблицу на экран, введя имя таблицы в консоль:

rownames(voenvuz.final) = c(1:length(voenvuz.final$ID))
voenvuz.final

Заключение

Описанные выше способы редактирования данных в таблице не уникальны, существует множество других методов и команд, позволяющих получить желаемый результат. Я рассказал лишь о наиболее простых и часто используемых. Для более детального ознакомления с этой темой я хотел бы порекомендовать два источника на английском языке:

  1. сайт http://stackoverflow.com/ (уже подробно разобраны тысячи вопросов по этой теме)
  2. книгу-справочник "R book" by Michael J. Crawley (легко найти бесплатную PDF версию в интернете).

Если у Вас возникли вопросы или проблемы с редактированием таблиц данных, Вы всегда можете оставить комментарий под этой статьей, и он не останется без внимания. А в качестве продолжения, читайте следующую статью, посвященную сохранению данных в среде R.

Комментарии: 29
  1. Alex

    Samoedd приветствую!!!
    Вопрос
    После расчетов на экране отображается таблица в таком формате

    Qtr1 Qtr2 Qtr3 Qtr4
    2000 119.28993 118.89396 118.10201 116.91410
    2001 115.33021 114.48457 114.37718 115.00804
    2002 116.37716 117.13394 117.27839 116.81051
    2003 115.73031 114.20610 112.23790 109.82569
    2004 106.96949 105.67921 105.95486 107.79644
    2005 111.20394 112.48537 111.64071 108.66998

    как ее вывести в таком формате?
    2000Qtr1 119.28993
    2000Qtr2 118.89396
    2000Qtr3 118.10201
    2000Qtr4 116.91410
    2001Qtr1 115.33021
    2001Qtr2 114.48457
    2001Qtr3 114.37718
    2001Qtr4 115.00804
    2002Qtr1 116.37716
    2002Qtr2 117.13394
    2002Qtr3 117.27839
    2002Qtr4 116.81051
    ….
    Чтобы потом скопировать ее вставить в Exсel.

    Сам пробовал искать ответ, но видимо это настолько просто, что об этом ни где не пишут. :-)
    Заранее спасибо.

    1. Samoedd (Автор записи)
      https://samoedd.com

      Здравствуйте, Alex! Извините, был в отпуске, не смог ответить. Ваш вопрос еще актуален или уже решен?

      1. Alex

        Еще актуален

      2. Samoedd (Автор записи)
        https://samoedd.com

        Здравствуйте, Alex!

        Тут загвоздка в том, что это не таблица, а матрица. Я не знаю имени Вашей матрицы, но допустим она называется mat. Ее нужно просто конвертировать в таблицу, которую я назвал df, где колонка 1 — это год, колонка 2 — квартал, колонка 3 — частота:
        df <- as.data.frame(as.table(mat))
        colnames(df) <- c("Year", "Qtr", "Freq")

        Если нужно слить первые две колонки слить, как в Вашем примере, то запустите следующие команды, чтобы получить желаемую таблицу df1:
        a <- paste(df$Year, df$Qtr, sep = "")
        df1 <- as.data.frame(cbind(a, df$Freq))
        colnames(df1) <- c("YearQtr", "Freq")

  2. Oleg

    Здравствуйте! Если при чтении csv числовые данные с пробелами в тысячных разрядах как такие колонки преобразовать в integer ?

    1. Samoedd (Автор записи)
      https://samoedd.com

      Здравствуйте, Олег! Загрузите таблицу как обычно, а потом преобразуйте загруженные столбцы, содержащие данные с пробелами, из текстового формата в числовой при помощи функции as.numeric. Внутри мы вызываем функцию gsub, куда вписываете текущий разделитель тысяч (в Вашем случае пробел " "), желаемый разделитель тысяч (в Вашем случае — это отсутствие разделителя ""), а также имя столбца или столбцов. Вот пример:

      MyTable$MyColumn < - as.numeric(gsub(" ", "", MyTable$MyColumn))

      1. Oleg
        https://autoline.info/

        Что-то не работает.. в результате данные преобразовуются в NA. В чем может быть проблема?

      2. Samoedd (Автор записи)
        https://samoedd.com

        Пришлите мне Ваш файл данных на sergey[собака]samoedd.com, и я решу Вашу проблему.

      3. Samoedd (Автор записи)
        https://samoedd.com

        Спасибо за файл. Выяснил в чем была загвоздка: у этой функции нестандартная кодировка пробелов и прочих разделителей. Поэтому вместо пробела " " нужно вписать "\\s" (подробности можете прочитать тут).

        В итоге, Ваш код будет выглядеть так:

        MyTable <- read.table("vds.csv", header = T, sep = ",") as.numeric(gsub("\\s", "", MyTable$События))

      4. Oleg

        Спасибо за помощь и оперативный ответ!

  3. Алексей

    Здравствуйте!
    Подскажите как можно переименовать всех Alexey в Alex?

    1. Samoedd (Автор записи)
      https://samoedd.com

      Если во всей таблице (df — название таблицы, замените ее на свое), то вот так:
      df[df == "Alexey"] < - "Alex"

      Если в определенном столбце (например, в колонке Name), то так:
      df$Name[df$Name == "Alexey"] < - "Alex"

      1. Алексей

        Спасибо, работает! Еще такой рабочий способ подсказали только что
        df$Name <- ifelse(df$Name == "Alexey", "Alex", df$Name)

  4. Алексей

    Подскажите как добавить перед текстом в ячейке свои данные? Например, в строке 1, столбца Name есть имя Vanya, и нужно дописать Ivanov, чтобы получилось Ivanov Vanya.

    1. Алексей

      Разобрался, добавить можно так voenvuz$Name <- paste("Ivanov", voenvuz$Name,sep=" ")

      1. Samoedd (Автор записи)
        https://samoedd.com

        Не успел ответить:-)

        Хорошее решение!!! Можно также переписать существующее значение:
        voenvuz[1, "Name"] < - "Vanya Ivanov"

        Однако, с точки зрения структуры таблицы, лучше добавьте колонку Surname (Фамилия) и тогда будет удобнее сортировать, редактировать и анализировать данные. При необходимости объединения столбцов Name и Surname, просто примените функцию paste для этих столбцов в новый Name_Surname столбец и имена с фамилиями объединятся автоматически:

        voenvuz$Name_Surname < - paste(voenvuz$Name, voenvuz$Surname, sep=" ")

  5. Алексей

    здравствуйте,
    что делать в случае, если таблицы загружаются корректно (на примере csv, разделитель ; , header = true) — выводит полную таблицу с наименованием заголовков, но команды анализа не проходят — ни head, ни summary, ни какие-либо еще:
    > head(«Test1.txt»)
    [1] «Test1.txt»
    или
    > summary(«Test1.csv»)
    Length Class Mode
    1 character character
    Если писать без кавычек, оно файл вообще не видит.

    1. Алексей

      Небольшая поправка: R-commander csv (и другие форматы) ест, а само R-studio даже принимает некоторые команды, которые копируются из коммандера. Но напрямую работать с таблицей данных не хочет. Например:
      with(Dataset, Hist(mmm, scale=»percent», breaks=»Sturges», col=»red», xlab=»Кгчт», ylab=»Доля», main=»»)) (mmm — это столбец) — выдает что надо, гистограмму с измененным цветом, а на это:
      Hist(`Test1.csv$M`, scale=»percent», breaks=»Sturges», col=»red», xlab=»Кгчт», ylab=»Доля», main=»»)
      ругается:
      Error in hist.default(x, axes = FALSE, xlab = xlab, ylab = ylab, main = main, :
      invalid number of ‘breaks’
      Т.е. например, через коммандер я могу ввести таблицу и построить гистограмму, а без его использования почему-то не выходит — программа отказывается работать с данными.

      1. Samoedd (Автор записи)
        https://samoedd.com

        Здравствуйте, Алексей. Я Rcmdr не пользовался, поэтому не знаю как команды копируются оттуда.
        Скиньте пожалуйста ссылку на Ваш файл и напишите код, с помощью которой Вы загружаете таблицу в Rstudio. Также рекомендую посмотреть как я загружал данные тут: https://samoedd.com/soft/r-import

      2. Алексей

        Добрый вечер.
        Файл тут — https://yadi.sk/i/giBeNDQkTEF4pw
        Команды:
        read.csv(«Test1.csv», sep = «;», header = TRUE)
        str(«Test1.csv»)
        head(«Test1.csv»)
        summary(‘Test1.csv$M’)

        Путь к файлу не прописан, т.к. он лежит в заранее определенной директории
        После команды read.csv программа показывает ряд данных — 130 строк. Разделитель ; более корректен, т.к. с разделителем , столбцы отдельно не воспринимаются.
        Остальные команды — попытки протестировать, как программа восприняла файл.
        з.ы. файлы загружал в соответствии с Вашей инструкцией

      3. Samoedd (Автор записи)
        https://samoedd.com

        Все, понял. При загрузке данных Вы забыли присвоить ей имя: в R она загрузилась, ее содержание отобразилось в консоли, но она но не сохранилась в виде переменной, т.е. R ее не «запомнил». Чтобы R сохранил таблицу у себя в памяти, дайте ей имя и после этого можно будет проводить операции с ней.

        Рассмотрим на конкретно Вашем примере. Допустим, Вы решили назвать Вашу таблицу mydata (советую выбирать названия покороче, ускоряет работу в R):

        mydata < - read.csv(«Test1.csv», sep = «;», header = TRUE)
        str(mydata)
        head(mydata)
        summary(mydata$M)

        Рад помочь Вам в освоении языка R. Если возникнут вопросы или сложности, всегда обращайтесь!
        С уважением, Сергей

  6. Александр

    Добрый всем вечер! Помогите, пожалуйста, кому не сложно, решить мою проблемку в R. Я не знаю r совсем, но есть желание научиться, но есть необходимость в таблице, которую я импортирую в r, оставить только повторяющиеся строки. Т.е. есть строки в столбце с повторениями, таких повторений может быть по 10 штук в 1 таблице. Как сделать так, чтобы в таблице остались только повторяющиеся строки? Например есть строки
    1431
    7777
    1431
    1431
    , нужно чтобы осталось только 1431 одна строка.

    1. Samoedd (Автор записи)
      https://samoedd.com

      Здравствуйте, Александр! Вашу проблему можно решить таким способом:

      new.df < - df[!duplicated(df$value),]

      где df — это имя Вашей таблицы, new.df — имя новой таблицы, value — имя столбца, содержащего повторяющиеся значения. Важно отметить, что такой метод будет извлекать только впервые повстречавшиеся значения в столбце вместе со всей строкой, игнорируя строки с повторяющимися значениями.

  7. Владимир

    Здравствуйте, а если мне нужно данные из одного столбика разбить на несколько? Допустим, в одном столбике в ячейках есть текстовая информация про то, есть ли в квартире wi-fi, телевизор или кондиционер, как разбить этот столбик на три, где в одном будут значения 1 или 0 для wi-fi, во втором 1 или 0 для телевизора и в третьем 1 или 0 для интернета, соотвественно изначальный столбик такого вида:

    Удобства_в_квартире
    1 Wi-fi,телевизор
    2 Wi-fi
    3 Na
    4 Na
    5 Кондиционер
    6 Wi-fi, кондиционер

    1. Samoedd
      https://samoedd.com

      Здравствуйте, Владимир!

      Сам с подобной проблемой не сталкивался, поэтому на данный момент вижу лишь два варианта:

      1) если позиций немного, то разделите этот столбик на три, и вручную вбейте данные в таблицу (как, собственно, Вы сами описали)
      2) если у Вас тысячи позиций, воспользуйтесь одним из ответов на этой страничке: https://stackoverflow.com/questions/4350440/split-a-column-of-a-data-frame-to-multiple-columns

  8. Юрий

    Просто недавно открыл для себя язык R и Rstudio. Для новичка посоветовали Ваш сайт. Ваши статьи помогли в первых шагах, спасибо)

    1. Samoedd (Автор записи)
      https://samoedd.com

      Вам спасибо, что читаете:-)

  9. Юрий

    Таблица же называется voenvuz_clean? По крайне мере скачанная по ссылке.

    1. Samoedd (Автор записи)
      https://samoedd.com

      Здравствуйте, Юрий! Да, voenvuz_clean. При загрузке таблицы в R не забудьте добавить к имени расширение .xlsx.

Оставить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *