如何将 key/value 字符串转换为不同的行?
How to transform a key/value string into distinct rows?
我有一个包含键值字符串的 R 数据集,如下所示:
quest<-data.frame(city=c("Atlanta","New York","Atlanta","Tampa"), key_value=c("rev=63;qty=1;zip=45987","rev=10.60|34;qty=1|2;zip=12686|12694","rev=12;qty=1;zip=74268","rev=3|24|8;qty=1|6|3;zip=33684|36842|30254"))
转换为:
city key_value
1 Atlanta rev=63;qty=1;zip=45987
2 New York rev=10.60|34;qty=1|2;zip=12686|12694
3 Atlanta rev=12;qty=1;zip=74268
4 Tampa rev=3|24|8;qty=1|6|3;zip=33684|36842|30254
基于上面的数据框,我如何创建一个如下所示的新数据框:
city rev qty zip
1 Atlanta 63.0 1 45987
2 New York 10.6 1 12686
3 New York 34.0 2 12686
4 Atlanta 12.0 1 74268
5 Tampa 3.0 1 33684
6 Tampa 24.0 6 33684
7 Tampa 8.0 3 33684
"|"是通用分隔符,它将确定要创建的行数。
我们可以使用tidyverse
。使用 separate_rows
,将 'key_value' 拆分为 ;
并展开行,然后将 separate
列分为两列('key','value' 在 =
,展开|
处的行(separate_rows
),按'city','key'分组,得到序号(row_number()
)和spread
到 'wide' 格式
library(tidyverse)
separate_rows(quest, key_value, sep=";") %>%
separate(key_value, into = c("key", "value"), sep="=") %>%
separate_rows(value, sep="[|]", convert = TRUE) %>%
group_by(city, key) %>%
mutate(rn = row_number()) %>%
spread(key, value) %>%
select(-rn)
# A tibble: 7 x 4
# Groups: city [3]
# city qty rev zip
#* <fctr> <dbl> <dbl> <dbl>
#1 Atlanta 1 63.0 45987
#2 Atlanta 1 12.0 74268
#3 New York 1 10.6 12686
#4 New York 2 34.0 12694
#5 Tampa 1 3.0 33684
#6 Tampa 6 24.0 36842
#7 Tampa 3 8.0 30254
由;
分割,再由=
和|
分割,组合成矩阵,以第一部分为名。然后重复原始数据框的行,无论为每行找到多少行,然后合并。我没有在这里将任何列转换为数字,它们保留为字符。
a <- strsplit(as.character(quest$key_value), ";")
a <- lapply(a, function(x) {
x <- do.call(cbind, strsplit(x, "[=|]"))
colnames(x) <- x[1,]
x[-1,,drop=FALSE]
})
b <- quest[rep(seq_along(a), sapply(a, nrow)), colnames(quest) != "key_value", drop=FALSE]
out <- cbind(b, do.call(rbind, a), stringsAsFactors=FALSE)
rownames(out) <- NULL
out
## city rev qty zip
## 1 Atlanta 63 1 45987
## 2 New York 10.60 1 12686
## 3 New York 34 2 12694
## 4 Atlanta 12 1 74268
## 5 Tampa 3 1 33684
## 6 Tampa 24 6 36842
## 7 Tampa 8 3 30254
我有一个包含键值字符串的 R 数据集,如下所示:
quest<-data.frame(city=c("Atlanta","New York","Atlanta","Tampa"), key_value=c("rev=63;qty=1;zip=45987","rev=10.60|34;qty=1|2;zip=12686|12694","rev=12;qty=1;zip=74268","rev=3|24|8;qty=1|6|3;zip=33684|36842|30254"))
转换为:
city key_value
1 Atlanta rev=63;qty=1;zip=45987
2 New York rev=10.60|34;qty=1|2;zip=12686|12694
3 Atlanta rev=12;qty=1;zip=74268
4 Tampa rev=3|24|8;qty=1|6|3;zip=33684|36842|30254
基于上面的数据框,我如何创建一个如下所示的新数据框:
city rev qty zip
1 Atlanta 63.0 1 45987
2 New York 10.6 1 12686
3 New York 34.0 2 12686
4 Atlanta 12.0 1 74268
5 Tampa 3.0 1 33684
6 Tampa 24.0 6 33684
7 Tampa 8.0 3 33684
"|"是通用分隔符,它将确定要创建的行数。
我们可以使用tidyverse
。使用 separate_rows
,将 'key_value' 拆分为 ;
并展开行,然后将 separate
列分为两列('key','value' 在 =
,展开|
处的行(separate_rows
),按'city','key'分组,得到序号(row_number()
)和spread
到 'wide' 格式
library(tidyverse)
separate_rows(quest, key_value, sep=";") %>%
separate(key_value, into = c("key", "value"), sep="=") %>%
separate_rows(value, sep="[|]", convert = TRUE) %>%
group_by(city, key) %>%
mutate(rn = row_number()) %>%
spread(key, value) %>%
select(-rn)
# A tibble: 7 x 4
# Groups: city [3]
# city qty rev zip
#* <fctr> <dbl> <dbl> <dbl>
#1 Atlanta 1 63.0 45987
#2 Atlanta 1 12.0 74268
#3 New York 1 10.6 12686
#4 New York 2 34.0 12694
#5 Tampa 1 3.0 33684
#6 Tampa 6 24.0 36842
#7 Tampa 3 8.0 30254
由;
分割,再由=
和|
分割,组合成矩阵,以第一部分为名。然后重复原始数据框的行,无论为每行找到多少行,然后合并。我没有在这里将任何列转换为数字,它们保留为字符。
a <- strsplit(as.character(quest$key_value), ";")
a <- lapply(a, function(x) {
x <- do.call(cbind, strsplit(x, "[=|]"))
colnames(x) <- x[1,]
x[-1,,drop=FALSE]
})
b <- quest[rep(seq_along(a), sapply(a, nrow)), colnames(quest) != "key_value", drop=FALSE]
out <- cbind(b, do.call(rbind, a), stringsAsFactors=FALSE)
rownames(out) <- NULL
out
## city rev qty zip
## 1 Atlanta 63 1 45987
## 2 New York 10.60 1 12686
## 3 New York 34 2 12694
## 4 Atlanta 12 1 74268
## 5 Tampa 3 1 33684
## 6 Tampa 24 6 36842
## 7 Tampa 8 3 30254