Одна вещь, которую я заметил, это то, что когда вы вызывали каждую функцию с помощью 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