QHoang
QHoang

Reputation: 45

Plot multiple lines (data series) with unique colors and custom x_axis in R

I'm trying to generate a plot in R which has multiple lines (each line represents a different category), each with unique colors. The x-axis is the time, which start at 17:00 and end at 9:00 the next day. The y-axis is the frequency (i.e. number of counts) of each category at certain time. Please have a look at the csv file that I use to plot this:

Time,-3,-2.5,-2,-1.5,-1,-0.5,0,0.5,1,1.5,2,2.5,3
0,0,0,0,0,0,0,288,224,148,78,37,23,19
1,0,0,0,0,0,0,321,208,128,74,55,20,11
2,0,0,0,0,0,0,326,212,128,80,46,20,5
3,0,0,0,0,0,0,345,209,131,73,36,17,6
4,0,0,0,0,0,0,364,201,117,77,38,15,5
5,0,0,0,0,0,0,390,205,100,73,36,10,3
6,0,0,0,0,0,0,406,196,121,57,24,8,5
7,0,0,0,0,0,1,560,161,62,25,5,3,0
8,0,0,0,0,0,18,772,22,5,0,0,0,0
9,0,0,0,0,18,130,667,1,0,1,0,0,0
10,0,0,0,2,55,256,503,1,0,0,0,0,0
11,1,0,0,7,106,349,354,0,0,0,0,0,0
12,1,1,0,12,184,368,251,0,0,0,0,0,0
13,0,0,0,32,228,357,200,0,0,0,0,0,0
14,0,0,0,51,245,314,208,0,0,0,0,0,0
15,0,0,0,51,232,317,218,0,0,0,0,0,0
16,0,0,0,37,224,338,218,1,0,0,0,0,0
17,0,0,0,21,156,350,290,1,0,0,0,0,0
18,0,0,0,2,72,351,392,1,0,0,0,0,0
19,0,0,0,0,15,207,587,9,0,0,0,0,0
20,0,0,0,0,1,33,748,34,2,0,0,0,0
21,0,0,0,0,0,3,609,137,51,12,4,1,1
22,0,0,0,0,0,0,325,241,133,71,31,11,6
23,0,0,0,0,0,0,272,227,149,82,50,21,17

Aside from column Time, each column represent a category (i.e. -3, -2.5, -2, etc...). At time 0, category -3 appears 0 times while category 3 appear 19 times and so on. I want my lines to represent the categories and show the frequency of each category over time on the graph (similar to this question, but instead of just crimeFreq I have multiple categories here.

Another 2 things are:

  1. My x-axis need to start from 17 (means 17:00 or 5pm) to 9 (means 9:00) or 9am).
  2. I only need the categories that are ">= 0" (i.e. 0, 0.5, 1, etc...)

I have tried the solution above and solution from this question but was not being able to success. Some of my attempts are:

Attempt 1:

df = read.csv("data_summary.csv")

// Taking the rows in the order of time that I want (i.e. from 17:00 to 9:00)
row_to_take = c(18,19,20,21,22,23, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 

// Tring to plot it with x-axis in desired order
matplot(x = df$Time[row_to_take], y = df[row_to_take, 9:14], ylab = "Frequency", xlab = "Hour", type = c("b"), pch=3, col = 1:7, xaxt="n" )
axis(1, at = c(17, 18, 19, 20, 21, 22, 23, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9), las=0)
legend("topleft", legend = 1:7, col=1:7, pch=3)

However, this attempt does not generate a correct graph (incorrect x-axis and the category that was represent by the black color got drawn twice)

My second attempt:

ggplot(df, aes(Time)) + geom_line(aes(y = 0, colour = "0")) + 
geom_line(aes(y = 0.5, colour = "0.5")) + geom_line(aes(y = 1, colour = "1"))+
geom_line(aes(y = 1.5, colour = "1.5"))+ geom_line(aes(y = 2, colour = "2"))+ 
geom_line(aes(y = 2.5, colour = "2.5"))+ geom_line(aes(y = 3, colour = "3"))

This attemp has the same problem with the first attemp. Also, I don't know how to change the legend's name for each color and the axis's name (xlab and ylab doesn't work ??)

Please suggest me a simple solution. I'm very new in R and don't know much about advance functions/packages. Thanks you all in advance :)

Upvotes: 0

Views: 79

Answers (2)

QHoang
QHoang

Reputation: 45

I combined the answer above from @Quinten and this answer: Setting limits with scale_x_time and was able to come up with this:

df = read.csv("data_summary.csv", check.names = FALSE, header = TRUE)

df$Time <- as.POSIXct(df$Time)
df %>% 
  pivot_longer(cols = -Time) %>%
  filter(name > 0) %>%
  ggplot(aes(x=Time, y=value, color=name)) + 
    geom_line()+
    labs(x="Time", y="Frequency", title="")+
  theme_bw() + 
  theme(axis.text.x = element_text(angle = 90, hjust = 1,family="Times", 
                                   face="bold", size=12), 
        axis.text.y = element_text(family="Times", face="bold", size=12),
        strip.text = element_text(size=6, face="bold")) + 
  scale_y_continuous(expand = expansion(mult = c(0, .1))) +
  scale_x_datetime(date_labels = '%T', 
                   limits = c(as.POSIXct('2022-08-24 22:00:00', tz = 'UTC'), 
                              as.POSIXct('2022-08-25 14:00:00', tz = 'UTC')), 
                   breaks = '1 hours')

The code yields this graph:enter image description here

which is what I need. Note that I have to change my "Time" column into the format: 0:00, 1:00,etc... so that I can use as.POSIXct(df$Time) on it.

Upvotes: 0

Quinten
Quinten

Reputation: 41337

You could use the lovely package ggplot2. First, you should make your dataframe in a longer format using pivot_longer and then you can assign each category as a line with color. You can filter the categories like this:

df <- read.table(text = "Time,-3,-2.5,-2,-1.5,-1,-0.5,0,0.5,1,1.5,2,2.5,3
0,0,0,0,0,0,0,288,224,148,78,37,23,19
1,0,0,0,0,0,0,321,208,128,74,55,20,11
2,0,0,0,0,0,0,326,212,128,80,46,20,5
3,0,0,0,0,0,0,345,209,131,73,36,17,6
4,0,0,0,0,0,0,364,201,117,77,38,15,5
5,0,0,0,0,0,0,390,205,100,73,36,10,3
6,0,0,0,0,0,0,406,196,121,57,24,8,5
7,0,0,0,0,0,1,560,161,62,25,5,3,0
8,0,0,0,0,0,18,772,22,5,0,0,0,0
9,0,0,0,0,18,130,667,1,0,1,0,0,0
10,0,0,0,2,55,256,503,1,0,0,0,0,0
11,1,0,0,7,106,349,354,0,0,0,0,0,0
12,1,1,0,12,184,368,251,0,0,0,0,0,0
13,0,0,0,32,228,357,200,0,0,0,0,0,0
14,0,0,0,51,245,314,208,0,0,0,0,0,0
15,0,0,0,51,232,317,218,0,0,0,0,0,0
16,0,0,0,37,224,338,218,1,0,0,0,0,0
17,0,0,0,21,156,350,290,1,0,0,0,0,0
18,0,0,0,2,72,351,392,1,0,0,0,0,0
19,0,0,0,0,15,207,587,9,0,0,0,0,0
20,0,0,0,0,1,33,748,34,2,0,0,0,0
21,0,0,0,0,0,3,609,137,51,12,4,1,1
22,0,0,0,0,0,0,325,241,133,71,31,11,6
23,0,0,0,0,0,0,272,227,149,82,50,21,17", header = TRUE, sep = ",", check.names = FALSE)

library(dplyr)
library(ggplot2)
library(tidyr)
df %>%
  pivot_longer(cols = -Time) %>%
  filter(name >= 0) %>%
  ggplot(aes(x = Time, y = value, colour = name)) +
  geom_line() +
  labs(x = "Time", y = "Value", colour = "Category")

Created on 2022-08-25 with reprex v2.0.2

Reverse x-axis values

You could use scale_x_continuous with "reverse":

library(dplyr)
library(ggplot2)
library(tidyr)
df %>%
  pivot_longer(cols = -Time) %>%
  filter(name >= 0) %>%
  filter(Time >= 9 & Time <= 17)  %>%
  ggplot(aes(x = Time, y = value, colour = name)) +
  geom_line() +
  scale_x_continuous(trans = "reverse") +
  labs(x = "Time", y = "Value", colour = "Category")

Created on 2022-08-25 with reprex v2.0.2

Upvotes: 1

Related Questions