Ошибка множителя матрицы - переключение максимального значения на сумму - PullRequest
0 голосов
/ 10 января 2020

У меня есть два кадра данных, один с информацией о животном, найденном в одном месте (df1), а другой с информацией о характеристиках c животного (df2)

Я пытаюсь использовать матричный множитель ( % *%) и применять такие функции, как «сумма» и «макс», и получать информацию в каждом месте.

Например,

df1:
 Location No. Dog Cat Cow Sheep
    1            0   2   2   1
    2            0   1   0   1
    3            0   0   0   1
    4            0   0   2   1

df2:
Name of Animal  BodySize   FavoriteScore
Dog             40         10
Cat             20         08
Cow             100        05
Sheep           60         07

Моя цель - получить такую ​​информацию, как: 1. Сколько видов животных в каждом месте? 2. Какое самое большое животное найдено в каждой локации? (где он сравнивает всех животных, выбирает самый большой размер тела и доставляет его) 3. Какое животное имеет самый высокий рейтинг FavoriteScore в каждой локации? (где он сравнивает всех животных и выбирает наибольшее количество избранных баллов и доставляет его)

Чтобы получить это, я использую следующий код:

Typemaker <- function (n) {
  o<-sum(n>0)
  return(o)
} 

apply(df1[,1:4] ,1, Typemaker)
df1$sumtype <- apply(df1[,2:5] ,1, Typemaker)

and 
Favoritemaker <- function (n) {
  o<- max(n %*% df2$FavoriteScore)
  return(o)
} 
apply(df1[,1:4] ,1, Favoritemaker)
df1$Favorite <-  apply(df1[,2:5] ,1, Favoritemaker)
or 
Bodysizemaker <- function (n) {
  o<- max(n %*% df2$BodySize)
  return(o)
} 
apply(df1[,1:4] ,1, Bodysizemaker).
df1$Bodysize <- apply(df1[,2:5] ,1, Bodysizemaker).

Чтобы мой ответ выглядел как :

 Location No. Dog Cat Cow Sheep Type Favorite Bodysize
    1            0   2   2   1     3    08       100
    2            0   1   0   1     2    08       20
    3            0   0   0   1     1    07       60
    4            0   0   2   1     2    07       100

Тем не менее, размер тела и избранные баллы указываются как сумма строки, а не как наибольшее значение.

Я не уверен, в чем именно заключается проблема.

Буду признателен за любую помощь.

1 Ответ

1 голос
/ 13 января 2020

Одна вещь, которую я заметил, это то, что когда вы вызывали каждую функцию с помощью apply, вы использовали первые четыре столбца, df1[,1:4], который включает номер местоположения и исключает данные об Овцах. Вы должны изменить это значение на df1[,2:5].

Я никогда не использовал матричный множитель, %*%, поэтому я не могу сказать, как правильно использовать его для этой проблемы, или даже если он правильный подходить. Но так как у вас есть фреймы данных, ниже очень неуклюжий способ использовать dplyr для получения желаемого результата:

library(tidyverse)

df1 <- data.frame(`Location No.` = c(1:4),
                  Dog = rep(0,4),
                  Cat = c(2,1,0,0),
                  Cow = c(2,0,0,2),
                  Sheep = rep(1,4))

df2 <- data.frame(`Name of Animal` = c("Dog", "Cat", "Cow", "Sheep"),
                  BodySize = c(40, 20, 100, 60),
                  FavoriteScore = c(10, 8, 5, 7))

dfout <- df1 %>% 
           mutate(DogSize = ifelse(Dog > 0, df2$BodySize[df2$Name.of.Animal == "Dog"], 0),
                  CatSize = ifelse(Cat > 0, df2$BodySize[df2$Name.of.Animal == "Cat"], 0),
                  CowSize = ifelse(Cow > 0, df2$BodySize[df2$Name.of.Animal == "Cow"], 0),
                  SheepSize = ifelse(Sheep > 0, df2$BodySize[df2$Name.of.Animal == "Sheep"], 0)) %>%
           mutate(DogScore = ifelse(Dog > 0, df2$FavoriteScore[df2$Name.of.Animal == "Dog"], 0),
                  CatScore = ifelse(Cat > 0, df2$FavoriteScore[df2$Name.of.Animal == "Cat"], 0),
                  CowScore = ifelse(Cow > 0, df2$FavoriteScore[df2$Name.of.Animal == "Cow"], 0),
                  SheepScore = ifelse(Sheep > 0, df2$FavoriteScore[df2$Name.of.Animal == "Sheep"], 0)) %>% 
           rowwise() %>% 
           mutate(Bodysize = max(DogSize, CatSize, CowSize, SheepSize),
                  Favorite = max(DogScore, CatScore, CowScore, SheepScore)) %>% 
           select(Location.No., Dog, Cat, Cow, Sheep, Favorite, Bodysize)

Определенно есть более эффективные способы сделать это, особенно если ваш набор данных больше, но это приведет вас к таблице, которую вы показали в конце вашего вопроса:

Location.No. Dog Cat Cow Sheep Favorite Bodysize
1            0   2   2   1     8        100
2            0   1   0   1     8        60
3            0   0   0   1     7        60
4            0   0   2   1     7        100

ОБНОВЛЕНИЕ

ОК, так что я был очень любопытен для себя Ниже приводится обновленный код, который использует сбор и распространение, чтобы сделать процесс более универсальным для набора данных с большим количеством столбцов. Это должно работать с большим количеством столбцов, при условии, что структура аналогична показанным образцам данных.

df_long <- gather(df1, animal, count, Dog:Sheep, factor_key = TRUE)

Это позволит получить первый кадр данных в широком формате и преобразовать его в длинный формат для упрощения манипулирования. Просто замените Dog:Sheep диапазоном ваших столбцов животных.

df_modified <- df_long %>% 
  rowwise() %>% 
  # assign favorite score and body size by animal
  mutate(Favorite = df2$FavoriteScore[df2$Name.of.Animal == animal],
         Bodysize = df2$BodySize[df2$Name.of.Animal == animal]) %>% 
  # eliminate score and body size for animals without a count
  mutate(Favorite = case_when(count == 0 ~ 0,
                          TRUE ~ Favorite)) %>% 
  mutate(Bodysize = case_when(count == 0 ~ 0,
                          TRUE ~ Bodysize)) %>% 
  # use group_by and max() to get the max value for each location
  group_by(Location.No.) %>% 
  mutate(Favorite = max(Favorite),
         Bodysize = max(Bodysize))


# use spread to put the data frame back into the wide format
df_wide <- spread(df_modified, animal, count)

# use as.data.frame to get from tibble to dataframe
df_out <- as.data.frame(df_wide)

Новый вывод выглядит так:

Location.No. Favorite Bodysize Dog Cat Cow Sheep
1            8        100      0   2   2   1
2            8        60       0   1   0   1
3            7        60       0   0   0   1
4            7        100      0   0   2   1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...