Решение регулярных выражений для имен строк данных - PullRequest
2 голосов
/ 19 апреля 2019

У меня есть фрейм данных, возвращенный из функции, которая выглядит следующим образом:

df <- data.frame(data = c(1,2,3,4,5,6,7,8))
rownames(df) <- c('firsta','firstb','firstc','firstd','seconda','secondb','secondc','secondd')

firsta  1
seconda 5
firstb  2
secondb 6

Моя цель состоит в том, чтобы превратить его в следующее:

df_goal <- data.frame(first = c(1,2,3,4), second = c(5,6,7,8))
rownames(df_goal) <- c('a','b','c','d')

    first    second
a   1        5
b   2        6

В основном проблема заключается в том, что существуетинформацию в именах строк, которую я не могу отбросить, потому что иначе нет способа различить значения столбца.

1 Ответ

4 голосов
/ 19 апреля 2019

Это простое преобразование длинных в широкие ;поворот заключается в том, что нам нужно сгенерировать ключевую переменную из имен строк, соответствующим образом разделив строку.

В данных, которые вы предоставляете, имя строки состоит из конкатенации «позиции» (т. е. «first»,'second') и идентификатор (то есть. 'a', 'b'), который застрял в конце.Структура этого делает его разделение сложным: в идеале, вы бы использовали разделитель (т.е. first_a, first_b), чтобы сделать разделение однозначным.Без разделителя наш единственный вариант - разделить по позиции, но для этого необходимо, чтобы позиция разделения была фиксированным расстоянием от начала или конца строки.

В вашем примере, идентификатор всегда является последнимсимвол, поэтому мы можем передать -1 аргументу sep в separate, чтобы отделить последний символ в качестве столбца идентификатора.Если это не всегда так, вам понадобится более сложное решение для разрешения имен строк.

После преобразования имен строк в столбцы "position" и "id" это простоважно использовать spread для расширения столбца позиции в широкоформатный формат:

library(tidyverse)
df %>%
    rownames_to_column('row') %>%
    separate(row, into = c('num', 'id'), sep = -1) %>%
    spread(num, data)

  id first second
1  a     1      5
2  b     2      6
3  c     3      7
4  d     4      8

Если бы идентификаторы строк могли иметь переменную длину, вышеприведенное решение не сработало бы.Если у вас есть известное и ограниченное количество значений «position», вы можете использовать решение регулярных выражений для разделения имени строки:

Здесь мы извлекаем значение позиции, сопоставляя регулярное выражение, содержащее все возможные значения (| является оператором ИЛИ.

Мы сопоставляем значение "id", помещая это же регулярное выражение в оператор положительного просмотра .Это регулярное выражение будет соответствовать 1 или более строчных букв, которые приходят сразу после совпадения со значением позиции.Недостатком этого подхода является то, что вам необходимо указать все возможные значения «позиции» в регулярном выражении - если есть много опций, это может быстро стать слишком длинным и трудным для поддержки:

df2
         data
firsta      1
firstb      2
firstc      3
firstd      4
seconda     5
secondb     6
secondc     7
secondd     8
secondee    9

df2 %>%
    rownames_to_column('row') %>%
    mutate(num = str_extract(row, 'first|second'),
           id = str_match(row, '(?<=first|second)[a-z]+')) %>%
    select(-row) %>%
    spread(num, data)

  id first second
1  a     1      5
2  b     2      6
3  c     3      7
4  d     4      8
5 ee    NA      9
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...