Как разложить таблицу из «ID», «Field», «Value» с повторяющимися строками «ID + Field», используя R / Tidyverse - PullRequest
0 голосов
/ 13 апреля 2020

У меня есть длинная таблица с идентификатором, полем и значением, которая имеет дубликаты на каждый идентификатор в столбце «Поле». См. Ссылку ниже:

Ссылка на цветное изображение

| 306428    | game.name         | Game Name     |
|--------   |-----------------  |-----------    |
| 306428    | game.year         | 2018          |
| 306428    | game.minplayers   | 2             |
| 306428    | game.maxplayers   | 4             |
| 306428    | game.category     | A             |
| 306428    | game.category     | B             |
| 306428    | game.category     | C             |
| 306428    | game.category     | D             |
| 306428    | game.category     | E             |
| 306428    | game.mechanic     | A             |

| id     | name      | year | minplayers | maxplayers | category  | category_count | mechanic | mechanic_count |
|--------|-----------|------|------------|------------|-----------|----------------|----------|----------------|
| 306428 | Game Name | 2018 | 2          | 4          | A|B|C|D|E | 5              | A        | 1              |

В конце игры также необходимо создать флаги для выбранного количества «множественных» полей (например, categoryF_A , categoryF_B) использовать для моделирования потенциального влияния на популярность / рейтинг. Полагаю, что объединенное поле в конечном итоге будет удалено.

| categories | categories_count | cat_A | cat_B | ... | cat_X |
|------------|------------------|-------|-------|-----|-------|
| A|B|C|D|E  | 5                | 1     | 1     | ... | 0     |

Я совершенно новичок, поэтому я уверен, что есть способ с меньшим количеством кода и потенциально более эффективный, но я концептуализировал, начиная со следующего (также см. обновление «Текущее решение»):

    new2<-games_data %>% group_by(game.id,field) %>% 
        summarise(Count_=length(value), Values = paste0(value,collapse="|"))
| game.id | field           | Count_ | Values    |
|---------|-----------------|--------|-----------|
| 306428  | game.year       | 1      | 2018      |
| 306428  | game.maxplayers | 1      | 4         |
| 306428  | game.minplayers | 1      | 2         |
| 306428  | game.category   | 5      | A|B|C|D|E |
| 306428  | game.mechanic   | 1      | A         |

, а затем объединили их в game.id. Затем я удаляю счетчики для столбцов с максимальным счетом 1 (снова см. Обновление «Текущее решение»).

Есть какие-нибудь мысли о правильном подходе к этому систематически или о функциях, которые могут сделать это для меня? Я играл с dcast, но сдался.

См. Ниже уменьшенные примеры данных для двух игр:

twogames <- data.frame(
  game.id = c("275539","275539","275539","275539","275539","275539","275539","275539","275539","275539","275539","275551","275551","275551","275551","275551","275551","275551","275551","275551","275551","275551","275551","275551")
  ,field = c("game.name","game.minplayers","game.maxplayers","game.categoryid","game.categoryid","game.categoryid","game.category","game.category","game.category","game.mechanicid","game.mechanic","game.name","game.minplayers","game.maxplayers","game.categoryid","game.categoryid","game.categoryid","game.category","game.category","game.category","game.mechanicid","game.mechanicid","game.mechanic","game.mechanic")
  ,value = c("Tower Beast Slayers: Catacombs Expansion","1","4","1042","1017","1010","Expansion for Base-game","Dice","Fantasy","2072","Dice Rolling","Sweet Treats!","1","4","1002","1041","1120","Card Game","Children's Game","Print & Play","2023","2004","Cooperative Game","Set Collection")
, stringsAsFactors = FALSE)

---- ТЕКУЩЕЕ РЕШЕНИЕ -----
Используя приведенные выше данные, я использую приведенный ниже код, чтобы получить приведенный ниже результат. Мысли ??

#Group by ID and Field and create Count and Concatenated Fields
twogames_sum <- twogames %>% group_by(game.id,field) %>% summarise(count=length(value),values=paste0(value, collapse = "|"))

##Create Counts and Values for all fields
counts <- twogames_sum %>% select(-values) %>% spread(key=field,value=count) %>% rename_at(vars(-game.id),~ paste0(.,"_count"))
values <- twogames_sum %>% select(-count) %>% spread(key=field,value=values)

##Merge Unique IDs, Counts, and Values to one table
main <- data.table(game.id = unique(twogames_sum$game.id))
main <- merge(main,counts, by = "game.id")
main <- merge(main,values, by = "game.id")

##Remove any columns that always have one value
remove <- colnames(main%>% select(ends_with("count")) %>% select_if(~all(. == 1)))
main<- main %>% select(!all_of(remove))


##Fields to Create Flags For
fields <- c("mechanic","category")

##ID List and Suffix for each Field
mechanic <- c("2072","2023","2004")
mechanic_names <- c("dice","coop","setc")
category <- c("1042","1017","1010","1002","1041","1120")
category_names <- c("exp","dice","fant","card","child","print")

##For each value in fields, loop through each identified value to create a flag
for (i in 1: length(fields)){
  field <- sym(fields[i])
  suffixlist <- eval(sym(paste0(fields[i],"_names")))
  valuelist <- eval(field)

  for(j in 1: length(valuelist)){
      column <- paste0("game.",field,"F_",suffixlist[j])
      fieldname <- sym(paste0("game.",field,"id"))
      value <- valuelist[j]
      #Use above 3 fields to add column
      main <- main %>% mutate(!!column := str_count(!!fieldname,!!value))
  }
}

Результат:

$ game.id               <dbl> 275539, 275551
$ game.category_count   <int> 3, 3
$ game.categoryid_count <int> 3, 3
$ game.mechanic_count   <int> 1, 2
$ game.mechanicid_count <int> 1, 2
$ game.category         <chr> "Expansion for Base-game|Dice|Fantasy", "Card Game|Children's Game|Print & Play"
$ game.categoryid       <chr> "1042|1017|1010", "1002|1041|1120"
$ game.maxplayers       <chr> "4", "4"
$ game.mechanic         <chr> "Dice Rolling", "Cooperative Game|Set Collection"
$ game.mechanicid       <chr> "2072", "2023|2004"
$ game.minplayers       <chr> "1", "1"
$ game.name             <chr> "Tower Beast Slayers: Catacombs Expansion", "Sweet Treats!"
$ game.mechanicF_dice   <int> 1, 0
$ game.mechanicF_coop   <int> 0, 1
$ game.mechanicF_setc   <int> 0, 1
$ game.categoryF_exp    <int> 1, 0
$ game.categoryF_dice   <int> 1, 0
$ game.categoryF_fant   <int> 1, 0
$ game.categoryF_card   <int> 0, 1
$ game.categoryF_child  <int> 0, 1
$ game.categoryF_print  <int> 0, 1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...