2017-09-20 45 views
2

我有密钥值串A R​​数据集,它看起来像下面: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 

“|”是共同的分隔符,它将确定要创建的行数。

回答

4

分割,然后通过=|,并组合成一个矩阵,使用所述第一部分作为名称。然后重复原始数据框的行由每行找到,然后合并。我不会将这里的任何列转换为数字,它们仍然是cha racter。

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 
+0

代码是否需要改变很多,如果输入的是一样的东西: 追求<-data.frame(市= C(“亚特兰大”,“纽约”,“亚特兰大”,“坦帕”) ,key_value = c(“type = a; qty = 1; zip = 45987”,“type = b; qty = 1 | 2; zip = 12686 | 12694”,“type = c; qty = 1; zip = 74268” ,“type = d; qty = 1 | 6 | 3; zip = 33684 | 36842 | 30254”)) 如何让“type”的单个值在内循环? –

+1

您是否尝试过反转解决方案?它可能只是工作。当'cbind'将部件组合在一起时,这个版本的长度取决于每个部件的长度。这是你必须努力的方向。 – Aaron

3

我们可以使用tidyverse。用separate_rows,将'key_value'分开;并将行扩展,然后将separate列分成两列('key','value'=,展开行|separate_rows),按'city','键分组通过;”,得到了序列号(row_number())和spread到‘宽’格式

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 
相关问题