我有下面这样的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分开仅允许除以“;”但是“;”的数量不同成行。我该怎么办?
答案 0 :(得分:2)
您可以使用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
)
答案 1 :(得分:1)
您可以使用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
由reprex package(v0.2.1)于2019-02-25创建
答案 2 :(得分:1)
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
答案 3 :(得分:1)
另一种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
第一步,它基于;
将“位置”分为“国家”和“城市”。然后,它从新创建的列中提取=
之后的元素。