2017-09-20 64 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 
相關問題