【问题标题】:How to convert long to wide format for single column with multiple categorical values如何将具有多个分类值的单列的长格式转换为宽格式
【发布时间】:2019-01-03 00:21:05
【问题描述】:

我的数据包含一个名为“states”的列,其中包含多个逗号分隔值,如下所示

test <- structure(list(states = c("WA", "SC", "IN", "IN", "WI", "NY",
"CA, CO, CT, DE, FL, GA, IA, ID, IL, IN, LA, MD, MI, MT, NJ, NV, OH, PA, SC, TX, UT, VA, WA", 
"CA, CO, DE, GA, IL, LA, MA, MD, MI, MO, NJ, NV, NY, PA, VA, TX, WA", 
"LA, MS", "DC, MD, VA", "AL, GA, NC", "MN WI", "MN WI", "KS, OK, TX", 
"KS, MO, OK, TX", "IN, MI, NY, OH, PA", "CO, NE", "CO", "CO, NE", 
"AZ, CA, CO, NV, TX, WA", "AZ, CA, NV, TX, UT,WA", "AZ, CA, NV, TX, UT, WA", 
"CA, CT, IL, WA", "AL, AZ, CA, IL, MI, MO, MT, NJ, NM, OH, OK, PA, TX, VA, WI", 
"AL, NC, TX, VA", "IL, MO, NJ, OH", "AZ, CA, CO, MN", "CO, IA, KY, TX", 
"CO, IA, KY, MI, NC, NE, OH, PA, TX", "AR, GA, NC, NM, OK", "AL & WV", 
"KY, MN, ND, OH,OR,PA", "KS", "AL, AR, AZ, CA, CT, DE, FL, GA, HI, IA, IL, IN, KS, KY, LA, MA, MD, MI, MN, MO, MS, NC, NE, NJ, NM, NY, OH, OK, OR, PA, RI, SC, TN, TX, UT, VA, WI", 
"AR, CO, GA, IL, LA, MI, MN, MS, MT, NC, ND, NE, OH, PA, RI, SC, TX, WI", 
"AL, AR, AZ, CA, CT, DE, FL, GA, HI, IA, IL, IN, KS, KY, LA, MA, MD, MI, MN, MO, MS, NC, NE, NJ, NM, NY, OH, OK, OR, PA, RI, SC, TN, TX, UT, VA, WI", 
"AL, AR, AZ, CA, CT, DE, FL, GA, HI, IA, IL, IN, KS, KY, LA, MA, MD, MI, MN, MO, MS, NC, NE, NJ, NM, NY, OH, OK, OR, PA, RI, SC, TN, TX, UT, VA, WI", 
"AL, AZ, FL, KS, MI, MN, MO, NC, OK, WI", "GA, SC", "CA, CO, FL, IL, KY, NJ, OH, TX, VA", 
"AL, AZ, CA, FL, GA, NJ, NM, NV, OH, PA, TX, VA", "ALL 50 STATES", 
"ALL 50 STATES", "ALL 50 STATES", "AL, AZ, FL, GA, MI, NJ, NY, OH, OR, PA, TX, UT"
)), .Names = "states", row.names = c(NA, -45L), class = c("tbl_df", 
                                                            "tbl", "data.frame"))
test

我想将其转换为一种格式,其中每个“状态”作为一列,1 表示状态存在,否则为零。

谢谢

【问题讨论】:

    标签: r dplyr tidyr


    【解决方案1】:

    这可能是你想要的。由于您没有提供预期的输出,这是我根据您的描述做出的解释。想法是用rowid_to_column添加索引,用“ALL”替换“ALL 50 STATES”,用separate_rows分隔基于符号和空格的状态,然后spread数据框。

    library(tidyverse)
    
    test2 <- test %>%
      # Create index
      rowid_to_column() %>%
      # Replace ALL 50 STATES with ALL
      mutate(states = replace(states, states %in% "ALL 50 STATES", "ALL")) %>%
      # Separate states with punct and space
      separate_rows(states, sep = "[[:punct:][:space:]]+") %>%
      group_by(rowid) %>%
      mutate(Group_ID = row_number(), Present = 1L) %>%
      spread(states, Present, fill = 0L) %>%
      select(-Group_ID)
    

    【讨论】:

    • 数据集中也有一些小问题需要考虑。例如,此解决方案为COCO 提供一个列,前面有一个空格,以及AL &amp; WVMN WI
    • @Lyngbakr 谢谢。我已根据您的建议更新了我的帖子。
    【解决方案2】:

    首先,我加载库。

    # Load libraries
    library(dplyr)
    library(magrittr)
    library(datasets)
    

    接下来,我将您的数据集中的ALL 50 STATES 替换为所有 50 个州的缩写。 (state.abb 来自 datasets 包。)

    # Change "ALL 50 STATES" to state abbreviations
    test %<>%
      mutate(states = ifelse(states == "ALL 50 STATES", paste0(state.abb, collapse = ","), states))
    

    最后,我遍历每个元素并使用strsplit 解析出状态,使用table 计算每个状态,使用bind_rows 将结果绑定到一个数据帧中,并将NAs 替换为零replace_namutate_all

    # Count assuming state only can appear once per row
    do.call(bind_rows, lapply(test$states, function(x)table(strsplit(x, "[[:punct:][:space:]]+")))) %>% 
      mutate_all(replace_na, replace = 0)
    

    [注意您的数据集有点乱:大多数状态用逗号分隔,但有些只有空格或 & 符号。我曾使用[[:punct:][:space:]]+ 来解释所有这些可能性。]

    这是前 10 行和前 10 个状态的示例:

    #      WA    SC    IN    WI    NY    CA    CO    CT    DE    FL
    #   <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
    # 1     1     0     0     0     0     0     0     0     0     0
    # 2     0     1     0     0     0     0     0     0     0     0
    # 3     0     0     1     0     0     0     0     0     0     0
    # 4     0     0     1     0     0     0     0     0     0     0
    # 5     0     0     0     1     0     0     0     0     0     0
    # 6     0     0     0     0     1     0     0     0     0     0
    # 7     1     1     1     0     0     1     1     1     1     1
    # 8     1     0     0     0     1     1     1     0     1     0
    # 9     0     0     0     0     0     0     0     0     0     0
    # 10    0     0     0     0     0     0     0     0     0     0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-18
      • 1970-01-01
      相关资源
      最近更新 更多