One option to remove the fill based on a logical condition is to change those values to NA.
library(tidyverse)
d <- head(mtcars) %>%
rownames_to_column() %>%
# make a new variable for fill
# note: don't use ifelse on a factor!
mutate(cyl_fill = ifelse(am == 0, NA, cyl),
# now make them factors
# (you can do this inside ggplot, but that is messy)
cyl = factor(cyl),
cyl_fill = factor(cyl_fill, levels = levels(cyl)))
# plot
p <- ggplot(d) +
aes(x = rowname,
y = mpg,
color = cyl,
fill = cyl_fill
) +
geom_bar(stat = "identity") +
theme(axis.text.x = element_text(angle = 90))
# change the fill color of NA values
p + scale_fill_discrete(drop=FALSE, na.value="white")

If you want NA fill values to be empty and omitted from the legend:
# omit the fill color of NA values
# note: drop=FALSE is still needed to keep the fill and (outline) color values the same
p + scale_fill_discrete(drop=FALSE, na.translate = F)

You can change the color of the outline in the same way (e.g. cyl_color = ifelse(am != 0, NA, Cyl)), but if you want to specify a color like white or black, it will (should) appear in the legend. You can try to hack your way around these wise defaults by plotting non-aesthetic layers behind your main layers, but it usually gets ugly:
head(mtcars) %>%
rownames_to_column() %>%
mutate(cyl_fill = ifelse(am == 0, NA, cyl),
cyl_color = ifelse(am != 0, NA, cyl),
cyl = factor(cyl),
cyl_fill = factor(cyl_fill, levels = levels(cyl)),
cyl_color = factor(cyl_color, levels = levels(cyl))) %>%
ggplot() +
aes(x = rowname,
y = mpg,
color = cyl_color,
fill = cyl_fill
) +
geom_bar(stat = "identity", color = "black") + # NON-AES LAYER FIRST
geom_bar(stat = "identity") + # Covers up the black except where omitted
theme(axis.text.x = element_text(angle = 90))+
scale_fill_discrete(drop=FALSE, na.translate = F) +
scale_color_discrete(drop=FALSE, na.translate = F)
