>我有两个数据框,一个是在一个位置发现的动物信息(df1(,另一个是关于动物特征的信息(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. 每个地点哪只动物的最爱分数最高?(其中比较所有动物,并选择最大的收藏夹分数并交付(
为了获得这个,我使用以下代码:
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
但是,正文大小和收藏夹分数作为行的总和而不是最大值提供。
我不确定到底是什么问题。
我将不胜感激任何帮助。
我注意到的一件事是,当您使用apply
调用每个函数时,您使用的是前四列,df1[,1:4]
包括位置编号并排除 Sheep 数据。 您应该将其更改为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