I'm trying to create a stacked bar graph showing body composition. I have a table/data set (I don't know the correct term) that looks like this:
structure(list(data.Date = structure(1:7, .Label = c("2021-03-06",
"2021-03-07", "2021-03-08", "2021-03-09", "2021-03-10", "2021-03-11",
"2021-03-12"), class = "factor"), total_bf = c(19.6612, 18.2182,
19.6803, 21.7047, 18.126, 19.7, 19.1424), total_muscle = c(41.5948,
43.043, 42.1578, 42.1866, 43.4017, 42.2, 42.2728), other = c(37.544,
38.8388, 38.0619, 38.0087, 39.1723, 38.1, 38.2848)), class = "data.frame", row.names = c(NA,
-7L))
Each column is a weight in kilograms. Together they add up to the total body weight of the subject. What I want is a stacked bar graph where each bar represents a date and each bar is split by total_bf, total_muscle and other. All of the guides and Q&As I've seen don't seem to apply to my situation. Maybe this is because I am new but nothing I've tried has worked yet.
An example of what I'm trying to achieve:
The only difference is that on my graph blue would be body fat (total_bf), green would be other and red would be muscle (total_muscle).
You can convert data from the wide format to the long format using tidyr::pivot_longer() function:
library(ggplot2)
df <- structure(list(
data.Date = structure(
1:7,
.Label = c("2021-03-06", "2021-03-07", "2021-03-08", "2021-03-09",
"2021-03-10", "2021-03-11", "2021-03-12"), class = "factor"),
total_bf = c(19.6612, 18.2182, 19.6803, 21.7047, 18.126, 19.7, 19.1424),
total_muscle = c(41.5948, 43.043, 42.1578, 42.1866, 43.4017, 42.2, 42.2728),
other = c(37.544, 38.8388, 38.0619, 38.0087, 39.1723, 38.1, 38.2848)
), class = "data.frame", row.names = c(NA, -7L))
long <- tidyr::pivot_longer(df, -data.Date)
Then using ggplot2, the defaults already make a stacked bar chart, so you just need to specify x, y and fill aesthetics.
ggplot(long, aes(data.Date, value, fill = name)) +
geom_col()
Since your date is encoded as a factor, if you want to encode it as a real date you can convert it as follows:
long$date <- as.Date(strptime(as.character(long$data.Date), format = "%Y-%m-%d"))
ggplot(long, aes(date, value, fill = name)) +
geom_col()
Created on 2021-03-12 by the reprex package (v0.3.0)
Related
I'm trying to assign different colors to the scatterplot based on their dates, more specifically the year.
This is how my dataset looks like:
> dput(head(CORt_r100_stack_join_fspec,10))
structure(list(Date = structure(c(16779, 16834, 16884, 16924,
16973, 16997, 17031, 17184, 17214, 17254), class = "Date"), meanNDVIN_int = c(0.677501157246889,
0.632728796482024, 0.578636981692124, 0.547002029242488, 0.632635423362751,
NA, 0.699596252720458, 0.670059391804396, 0.643347941166436,
0.674034259709311), meanNDVIW_int = c(0.784142418592418, 0.652437451242156,
0.648319814752948, 0.593432266488189, 0.767890365415717, NA,
0.779249089832163, 0.71974944410843, 0.715777992826006, 0.685045115352089
), meanNDVIE_int = c(0.703614512017928, 0.701963337684803, 0.488628353756438,
0.631309466083632, 0.781589421376217, NA, 0.799663418920722,
0.78910564747191, 0.710962969930836, 0.715644011856453), meanNDVINr_int_f = c(0.677501157246889,
0.632728796482024, 0.578636981692124, 0.547002029242488, 0.632635423362751,
0.687343078509066, 0.699596252720458, 0.670059391804396, 0.643347941166436,
0.674034259709311), meanNDVIWr_int_f = c(0.784142418592418, 0.652437451242156,
0.648319814752948, 0.593432266488189, 0.767890365415717, 0.749505859407419,
0.779249089832163, 0.71974944410843, 0.715777992826006, 0.685045115352089
), meanNDVIEr_int_f = c(0.703614512017928, 0.701963337684803,
0.488628353756438, 0.631309466083632, 0.781589421376217, 0.625916155640988,
0.799663418920722, 0.78910564747191, 0.710962969930836, 0.715644011856453
), NDVI_N = c(0.17221248, 0.644239685, 0.57222623, 0.558666635,
0.51654034, 0.42053949, 0.396706695, 0.641767447, 0.641008268,
0.662841949), NDVI_W = c(0.08182944, 0.69112807, 0.637699375,
0.629429605, 0.658829525, 0.60621678, 0.57186129, 0.72636742,
0.724193596, 0.738424976), NDVI_E = c(0.17135712, 0.659222803,
0.58665977, 0.573081253, 0.533498035, 0.437643585, 0.412841468,
0.652057206, 0.651854988, 0.670345511), NDVI_U = c(0.40520304,
0.578414833, 0.455746833, 0.428289893, 0.208847548, 0, 0, 0.475193691,
0.478691084, 0.505043773)), row.names = c(NA, 10L), class = "data.frame")
I've been plotting meanNDVIN_int against NDVI_N using this code:
ggplot(CORt_r100_join_fspec_2NDVIday,aes(x=NDVI_N)) +
geom_point(aes(y=meanNDVIN_int), colour="red")
theme_bw()+
ylab("meanNDVIN_int")+
xlab("NDVI_N")
Now I want to color each point differently (no matter the color) based on their year, 2015, 2016, and 2017.
I've used the scale_color_manual function to introduce the dates but no success so far.
Any help will be much appreciated.
Here is an alternative where you substring the first 4 characters from Date in color
df
ggplot(df,aes(x=NDVI_N)) +
geom_point(aes(y=meanNDVIN_int, color=substring(Date,1,4))) +
labs(color="Year")+
theme_bw()+
ylab("meanNDVIN_int")+
xlab("NDVI_N")
I created a year variable with lubridate and stored it asfactor for discrete colouring. You were just missing moving color inside the aes() to color it by year.
# Add year Variable;
CORt_r100_stack_join_fspec <- CORt_r100_stack_join_fspec %>% mutate(
year = as.factor(lubridate::year(Date))
)
# Plot;
ggplot(CORt_r100_stack_join_fspec,aes(x=NDVI_N)) +
geom_point(aes(y=meanNDVIN_int, color = year)) +
theme_bw() +
ylab("meanNDVIN_int")+
xlab("NDVI_N")
Note: The data you provided, and named is not the same as in your plot-call. So I changed CORt_r100_join_fspec_2NDVIday to CORt_r100_join_fspec_2NDVIday to make the plot and mutate function properly.
I would like to add a bracket using geom_bracket for my first two groups of countries the United Kingdom (UK) and France (FR). I use the following code and it plots the three estimates:
library(ggpubr)
library(ggplot2)
df %>%
ggplot(aes(estimate, cntry)) +
geom_point()
However, whenever i add the geom_bracket as below, i get an error. I tried to get around it in different ways but it is still not working. Could someone let me know what i am doing wrong?
df %>%
ggplot(aes(estimate, cntry)) +
geom_point() +
geom_bracket(ymin = "UK", ymax = "FR", x.position = -.75, label.size = 7,
label = "group 1")
Here is a reproducible example:
structure(list(cntry = structure(1:3, .Label = c("BE", "FR",
"UK"), class = "factor"), estimate = c(-0.748, 0.436,
-0.640)), row.names = c(NA, -3L), groups = structure(list(
cntry = structure(1:3, .Label = c("BE", "FR", "UK"), class = "factor"),
.rows = structure(list(1L, 2L, 3L), ptype = integer(0), class = c("vctrs_list_of",
"vctrs_vctr", "list"))), row.names = c(NA, 3L), class = c("tbl_df",
"tbl", "data.frame"), .drop = TRUE), class = c("grouped_df",
"tbl_df", "tbl", "data.frame"))
Well, it's pretty damn late at that, but I figured out a workaround for this. I though that I might as well post it here in case anyone finds it useful.
Firstly, as Basti mentioned, ymin, ymax, and x.position aren't arguments that can be used - you have to use xmin, xmax, and y.position. Now, won't this only work for a flipped graph (i.e. x = cntry, y = estimate)? Yes, it will. However you can easily get around this by using coord_flip().
Secondly, it turns out that geom_bracket doesn't inherit the data description (df) and won't run without it being defined inside it. Why? No idea. But this is what was causing the error. Additionally, for some reason, merely defining the data isn't enough, a label must also be added. Not a problem here, just thought I might mention it for dumb people like me who decided to use geom_bracket to add brackets to stat_compare_means.
Here's an example of the OP that should work, along with data generation:
library(ggplot2)
library(ggpubr)
library(tibble) #I like tibbles
df <- tibble(cntry = factor(c("BE", "FR", "UK")),
estimate = c(-0.748,0.436,-0.64)) #dataframe generation
df %>%
ggplot(aes(cntry, estimate)) +
geom_point() +
coord_flip() + #necessary if you want to keep this weird x/y orientation
geom_bracket(data = df, xmin = "UK", xmax = "FR", y.position = -.75,
label.size = 7, label = "group 1", coord.flip = T)
#coord.flip = T reflects the added coord_flip()
You can then play around with y coordinates, size, etc. You can also expand the graph using expand_limits().
I have the following code, that generates the following heatmap in R.
ggplot(data = hminput, color=category, aes(x = Poblaciones, y = Variantes)) +
geom_tile(aes(fill = Frecuencias)) + scale_colour_gradient(name = "Frecuencias",low = "blue", high = "white",guide="colourbar")
hminput is a data frame with three columns: Poblaciones, Variantes and Frecuencias, where the first two are the x and y axis and the third one is the color reference.
And my desired output is that the heatmap to have a bar as the reference instead of those blocks, and also that the coloring is white-blue gradient instead of that multicolor gradient.
To achieve that, I tried what's in my code, but I'm not achieving what I want (I'm getting the graph you see in the picture). Any thoughts? Thanks!
As some people asked, here is the dput of the data frame :
> dput(hminput)
structure(list(Variantes = structure(c(1L, 2L, 3L, 4L,...), .Label =
c("rs10498633", "rs10792832", "rs10838725",
"rs10948363", ..., "SNP"), class = "factor"),
Poblaciones = c("AFR", "AFR", ...), Frecuencias = structure(c(12L,
10L,...), .Label = c("0.01135", "0.0121",
"0.01286", "0.01513", "0.02194", "0.05144", "0.05825", "0.059",
"0.07716", "0.0938", "0.1051", "0.1225", "0.1346", "0.1407",
"0.1566", "0.1604", "0.1619", "0.1838", "0.1914", "0.1929",
...,
"0.45", "0.5", "0.4"), class = "factor")), .Names = c("Variantes",
"Poblaciones", "Frecuencias"), row.names = c("frqAFR.33", "frqAFR.31",
"frqAFR.27", "frqAFR.14", "frqAFR.24",...
), class = "data.frame")
I am trying to create a simple bar chart, but I keep receiving the error message
'height' must be a vector or a matrix
The barplot function I have been trying is
barplot(data, xlab="Percentage", ylab="Proportion")
I have inputted my csv, and the data looks as follows:
34.88372093 0.00029997
35.07751938 0.00019998
35.27131783 0.00029997
35.46511628 0.00029997
35.65891473 0.00069993
35.85271318 0.00069993
36.04651163 0.00049995
36.24031008 0.0009999
36.43410853 0.00189981
...
Where am I going wrong here?
Thanks in advance!
EDIT:
dput(head(data)) outputs:
structure(list(V1 = c(34.88372093, 35.07751938, 35.27131783,
35.46511628, 35.65891473, 35.85271318), V2 = c(0.00029997, 0.00019998,
0.00029997, 0.00029997, 0.00069993, 0.00069993)), .Names = c("V1",
"V2"), row.names = c(NA, 6L), class = "data.frame")
and barplot(as.matrix(data)) produced a chart with all the data one bar as opposed to each piece of data on a separate bar.
You can specify the two variables you want to plot rather than passing the whole data frame, like so:
data <- structure(list(V1 = c(34.88372093, 35.07751938, 35.27131783, 35.46511628, 35.65891473, 35.85271318),
V2 = c(0.00029997, 0.00019998, 0.00029997, 0.00029997, 0.00069993, 0.00069993)),
.Names = c("V1", "V2"), row.names = c(NA, 6L), class = "data.frame")
barplot(data$V2, data$V1, xlab="Percentage", ylab="Proportion")
Alternatively, you can use ggplot to do this:
library(ggplot2)
ggplot(data, aes(x=V1, y=V2)) + geom_bar(stat="identity") +
labs(x="Percentage", y="Proportion")
Probably the entire dataframe format is wrong, The same thing happened to me since I added the columns individually and made the dataframe together.
table.values = c(value1, value2,.......)
table = matrix(table.values,nrow=number of rows ,byrow = T)
colnames(table) = c("column1","column2",........)
row.names(table) = c("row1", "row2",............)
barplot(table, beside = T, xlab= "X-axis",ylab= "Y-axis")
My data looks something like this:
There are 10,000 rows, each representing a city and all months since 1998-01 to 2013-9:
RegionName| State| Metro| CountyName| 1998-01| 1998-02| 1998-03
New York| NY| New York| Queens| 1.3414| 1.344| 1.3514
Los Angeles| CA| Los Angeles| Los Angeles| 12.8841| 12.5466| 12.2737
Philadelphia| PA| Philadelphia| Philadelphia| 1.626| 0.5639| 0.2414
Phoenix| AZ| Phoenix| Maricopa| 2.7046| 2.5525| 2.3472
I want to be able to do a plot for all months since 1998 for any city or more than one city.
I tried this but i get an error. I am not sure if i am even attempting this right. Any help will be appreciated. Thank you.
forecl <- ts(forecl, start=c(1998, 1), end=c(2013, 9), frequency=12)
plot(forecl)
Error in plots(x = x, y = y, plot.type = plot.type, xy.labels = xy.labels, :
cannot plot more than 10 series as "multiple"
You might try
require(reshape)
require(ggplot2)
forecl <- melt(forecl, id.vars = c("region","state","city"), variable_name = "month")
forecl$month <- as.Date(forecl$month)
ggplot(forecl, aes(x = month, y = value, color = city)) + geom_line()
To add to #JLLagrange's answer, you might want to pass city through facet_grid() if there are too many cities and the colors will be hard to distinguish.
ggplot(forecl, aes(x = month, y = value, color = city, group = city)) +
geom_line() +
facet_grid( ~ city)
Could you provide an example of your data, e.g. dput(head(forecl)), before converting to a time-series object? The problem might also be with the ts object.
In any case, I think there are two problems.
First, data are in wide format. I'm not sure about your column names, since they should start with a letter, but in any case, the general idea would be do to something like this:
test <- structure(list(
city = structure(1:2, .Label = c("New York", "Philly"),
class = "factor"), state = structure(1:2, .Label = c("NY",
"PA"), class = "factor"), a2005.1 = c(1, 1), a2005.2 = c(2, 5
)), .Names = c("city", "state", "a2005.1", "a2005.2"), row.names = c(NA,
-2L), class = "data.frame")
test.long <- reshape(test, varying=c(3:4), direction="long")
Second, I think you are trying to plot too many cities at the same time. Try:
plot(forecl[, 1])
or
plot(forecl[, 1:5])