【问题标题】:Split/spread a DF column where differing values of for each observation拆分/散布 DF 列,其中每个观察值的不同值
【发布时间】:2019-08-06 18:08:23
【问题描述】:

假设我有一个如下的数据框:

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”下的向量中的每个不同值。

在深入研究循环和正则表达式之前,我想知道是否有人以前遇到过这个问题,是否有“正确”的方法来做到这一点?我一直在寻找 spread() 函数的 tidyr,但我不确定它是否适用于每个观察的每个向量中不同数量的字段。

如何处理 mydf 以在 map_of_blah 及其对应值中添加名称值对的附加字段?

【问题讨论】:

  • 当同一个俱乐部成员有多个值时,你想做什么?例如,club_member 0 同时具有 Upgrade = 1.0 和 Upgrade = 0.0022172949002217295
  • Club member 不是 id,而是一个布尔变量,表示用户是否是俱乐部成员。每行是一个用户。对不起,我的名字很糟糕
  • dplyr.tidyverse.org/reference/group_split.html -- 这可能就是你要找的。​​span>
  • 不用担心,这有帮助

标签: r


【解决方案1】:

这是str_extractspread 的一个选项。使用str_extract_all,从'map_of_blah' 获取相关子字符串作为list 列,unnest 数据集,更改类型(type_convertreadr)和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     

【讨论】:

    【解决方案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 映射中的所有项目分开,然后我们取消嵌套到长格式。之后,我们将列分开,以便获得两个新列(一个标题和一个值)。最后,我们向广泛传播。

    如果有什么不清楚的地方请告诉我。

    【讨论】:

    • 作为跟进。我的实际数据接近 5M 行,而且内存一直在用完。在这方面有什么想法可以提高效率吗?
    • 我确信有一些方法可以加快正则表达式部分。除此之外,我认为我没有任何想法。
    【解决方案3】:

    这是dplyrtidyr 的一种方式-

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-17
      • 2020-09-05
      • 2017-03-31
      • 2023-01-27
      • 2016-01-11
      • 2017-05-12
      • 1970-01-01
      • 2021-02-25
      相关资源
      最近更新 更多