R - разделительный столбец с разной длиной строк - PullRequest
0 голосов
/ 26 февраля 2019

У меня есть data.frame, как показано ниже

ID  age location
1   83  country=X;province=A;city=J
2   15  country=X;city=K
3   2   country=Y;province=B;city=I
4   12  country=X;city=L
5   2   country=Y;city=J
6   2   country=Y;province=A;city=M
7   18  country=X;province=B;city=J
8   85  country=X;province=A;city=I

Чтобы описать это: есть третий столбец (местоположение), в котором записи содержат строки, разделенные ";"и имеют разную длину.

В результате мне нужно получить data.frame следующим образом:

ID  age country city
1   83  X       J
2   15  X       K
3   2   Y       I
4   12  X       L
5   2   Y       J
6   2   Y       M
7   18  X       J
8   85  X       I

Чтобы описать - мне нужно разделить столбец и выбрать только записи о стране и городе (без провинции)).отдельно от dplyr разрешить только делить на ";"но есть другое число ";"в строках.Что мне делать?

Ответы [ 4 ]

0 голосов
/ 26 февраля 2019

Другая возможность tidyverse может быть:

df %>%
 separate(location, c("country", "city"), sep = ";") %>%
 mutate_at(3:4, funs(sub(".*=", "", .)))

  ID age country city
1  1  83       X    A
2  2  15       X    K
3  3   2       Y    B
4  4  12       X    L
5  5   2       Y    J
6  6   2       Y    A
7  7  18       X    B
8  8  85       X    A

На первом этапе он разделяет «местоположение» на «страну» и «город» на основе ;.Затем он извлекает элементы после = из вновь созданных столбцов.

0 голосов
/ 26 февраля 2019
df <- read.table(text='ID  age location
                 1   83  country=X;province=A;city=J
                 2   15  country=X;city=K
                 3   2   country=Y;province=B;city=I
                 4   12  country=X;city=L
                 5   2   country=Y;city=J
                 6   2   country=Y;province=A;city=M
                 7   18  country=X;province=B;city=J
                 8   85  country=X;province=A;city=I
                 ', header= T)




my_fun <- function(x){
  y <- as.data.frame(strsplit(x,'='))
  names(y) <- as.character(unlist(y[1,]))
  y <- y[-1,]
}

f <- strsplit(as.character(df$location), ";")
s <- data.table::rbindlist(lapply(f,my_fun), fill=T)

df$location <- NULL
df <- cbind(df, s)
df
  ID age country province city
1  1  83       X        A    J
2  2  15       X     <NA>    K
3  3   2       Y        B    I
4  4  12       X     <NA>    L
5  5   2       Y     <NA>    J
6  6   2       Y        A    M
7  7  18       X        B    J
8  8  85       X        A    I
0 голосов
/ 26 февраля 2019

Вы можете сделать это с помощью функции tidyr::extract:

library(tidyverse)

extract(
  data  = dat,
  col   = location,
  into  = c('country', 'city'),
  regex = "^country=([[:alpha:]]+).*city=([[:alpha:]]+)$"
  )

  ID age country city
1  1  83       X    J
2  2  15       X    K
3  3   2       Y    I
4  4  12       X    L
5  5   2       Y    J
6  6   2       Y    M
7  7  18       X    J
8  8  85       X    I

Данные

dat <- read.table(
  text = "ID  age location
1   83  country=X;province=A;city=J
2   15  country=X;city=K
3   2   country=Y;province=B;city=I
4   12  country=X;city=L
5   2   country=Y;city=J
6   2   country=Y;province=A;city=M
7   18  country=X;province=B;city=J
8   85  country=X;province=A;city=I",
  header = T, stringsAsFactors = F
)
0 голосов
/ 26 февраля 2019

Вы можете сделать это с помощью separate_rows и некоторого последующего изменения формы.separate_rows переводит вещи в длинный формат, поэтому мы можем выполнить некоторую фильтрацию, а затем spread, чтобы получить желаемый результат:

library(tidyverse)
tbl <- read_table2(
  "ID  age location
1   83  country=X;province=A;city=J
2   15  country=X;city=K
3   2   country=Y;province=B;city=I
4   12  country=X;city=L
5   2   country=Y;city=J
6   2   country=Y;province=A;city=M
7   18  country=X;province=B;city=J
8   85  country=X;province=A;city=I"
)

tbl %>%
  separate_rows(location, sep = ";") %>%
  separate(location, c("location_type", "value")) %>%
  filter(location_type %in% c("country", "city")) %>%
  spread(location_type, value)
#> # A tibble: 8 x 4
#>      ID   age city  country
#>   <dbl> <dbl> <chr> <chr>  
#> 1     1    83 J     X      
#> 2     2    15 K     X      
#> 3     3     2 I     Y      
#> 4     4    12 L     X      
#> 5     5     2 J     Y      
#> 6     6     2 M     Y      
#> 7     7    18 J     X      
#> 8     8    85 I     X

Поскольку у вас есть только два случая, вы можете найти их быстрееили проще просто использовать регулярное выражение для непосредственного извлечения интересующих значений:

tbl %>%
  mutate(
    country = str_extract(location, "(?<=country\\=)."),
    city = str_extract(location, "(?<=city\\=).")
  )
#> # A tibble: 8 x 5
#>      ID   age location                    country city 
#>   <dbl> <dbl> <chr>                       <chr>   <chr>
#> 1     1    83 country=X;province=A;city=J X       J    
#> 2     2    15 country=X;city=K            X       K    
#> 3     3     2 country=Y;province=B;city=I Y       I    
#> 4     4    12 country=X;city=L            X       L    
#> 5     5     2 country=Y;city=J            Y       J    
#> 6     6     2 country=Y;province=A;city=M Y       M    
#> 7     7    18 country=X;province=B;city=J X       J    
#> 8     8    85 country=X;province=A;city=I X       I

Создано в 2019-02-25 пакетом Представить (v0.2.1)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...