假设我有一个如下数据框:
mydf <- structure(list(club_member = c(0L, 0L, 1L, 0L, 0L, 0L), map_of_blah = c(NA,
"{Upgrade=1.0}", "{Apples=0.32786885245901637, In-Game Boost=0.06557377049180328, WalkoffGm=0.08196721311475409, Improve=0.5245901639344263}",
NA,
"{MystBox=0.9977827050997783, Upgrade=0.0022172949002217295, Apples = 1}",
NA)), row.names = c(NA, 6L), class = "data.frame")
glimpse(mydf)
Observations: 6
Variables: 2
$ club_member <int> 0, 0, 1, 0, 0, 0
$ map_of_blah <chr> NA, "{Upgrade=1.0}", "{Apples=0.32786885245901637, In-Game Boost=0.06557377049180328, WalkoffGm=0.08196721311475409, Improve=0.5245901639344263}", NA, "{MystBox=0.9977827050997783, …
mydf
club_member map_of_blah
1 0 <NA>
2 0 {Upgrade=1.0}
3 1 {Apples=0.32786885245901637, In-Game Boost=0.06557377049180328, WalkoffGm=0.08196721311475409, Improve=0.5245901639344263}
4 0 <NA>
5 0 {MystBox=0.9977827050997783, Upgrade=0.0022172949002217295, Apples = 1}
6 0 <NA>
我将数据直接从数据库中提取到r中,其中一种数据类型(Presto db)是其中r的数组映射。在r中,似乎已将其作为每个观察的字符向量读入。
“ map_of_blah”字段的每个矢量包含不同的值,但是数据集中总共可能有15到20个值,例如“ Apples”,“ In-Game Boost”,“ Improve”等。
我想将此字段处理为一个新的设置字段,每个字段对应于“ map_of_blah”下向量中包含的每个不同值。
在深入探讨循环和正则表达式之前,我想知道ayone之前是否曾遇到过这个问题,是否有一种“正确”的方式来做到这一点?我一直在寻找tidyr的spread()函数,但由于每个向量的每个观察场中的字段数不同,因此我不确定在这里是否适用。
如何处理mydf以在map_of_blah中的名称值对及其对应值中包含其他字段?
答案 0 :(得分:3)
这是str_extract
和spread
的一个选项。使用str_extract_all
,从“ map_of_blah”中获取相关子字符串作为list
列,unnest
数据集,更改类型(type_convert
来自readr
),并将spread
设置为“宽”格式
library(tidyverse)
mydf %>%
transmute(ID = row_number(), club_member,
key = str_extract_all(map_of_blah, "\\w+(?=\\=)"),
val = str_extract_all(map_of_blah, "(?<=\\=)[0-9.]+")) %>%
unnest(c(key, val)) %>%
type_convert %>%
spread(key, val) %>%
select(-"<NA>")
# A tibble: 6 x 8
# ID club_member Apples Boost Improve MystBox Upgrade WalkoffGm
# <int> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
#1 1 0 NA NA NA NA NA NA
#2 2 0 NA NA NA NA 1 NA
#3 3 1 0.328 0.0656 0.525 NA NA 0.0820
#4 4 0 NA NA NA NA NA NA
#5 5 0 NA NA NA 0.998 0.00222 NA
#6 6 0 NA NA NA NA NA NA
答案 1 :(得分:2)
尝试一下
library(tidyverse)
mydf %>%
rownames_to_column("ID") %>%
mutate(map_of_blah = str_remove_all(map_of_blah, "\\{|\\}") %>%
str_split(., ",\\s")) %>%
unnest() %>%
separate(col = map_of_blah, into = c("newcol", "newval"), sep = "=") %>%
mutate(newcol = str_trim(newcol, "both"),
newval = as.numeric(newval)) %>%
spread(newcol, newval)
我们首先为用户创建一个ID,然后我们将blah映射中的所有项目分开,然后我们将其格式化为长格式。之后,我们分离列,以便获得两个新的列(标题之一和值之一)。最后,我们传播到了广阔的范围。
让我知道是否有任何不清楚的地方。
答案 2 :(得分:1)
这里是dplyr
和tidyr
的一种方式-
mydf %>%
mutate(
user_id = 1:n(), # create id for each row
map_of_blah = gsub("\\{|\\}", "", map_of_blah) # remove {,}
) %>%
separate_rows(map_of_blah, sep = ",") %>% # separate attributes into rows
# separate attributes into columns
separate(map_of_blah, into = c("var", "value"), sep = "=", convert = T) %>%
mutate(var = trimws(var)) %>% # remove white spaces at the ends
spread(var, value) %>%
select(user_id, club_member, Apples:WalkoffGm)
user_id club_member Apples Improve In-Game Boost MystBox Upgrade WalkoffGm
1 1 0 NA NA NA NA NA NA
2 2 0 NA NA NA NA 1.000000000 NA
3 4 0 NA NA NA NA NA NA
4 5 0 1.0000000 NA NA 0.9977827 0.002217295 NA
5 6 0 NA NA NA NA NA NA
6 3 1 0.3278689 0.5245902 0.06557377 NA NA 0.08196721