我有OpenVPN作为VPN服务器在工作。我添加了很多其他功能。我将用户数据使用记录到MySQL数据库,如此布局。
id
username
IP
DateSessionStart
TimeSessionStart
SessionId
DateLastUpdate
TimeLastUpdate
UserUploaded
UserDownloaded
“SessionId”是会话开始的纪元时间。一个用户一天可能有多个会话,所以我不想使用geom_line
并将“aes”“color”属性设置为“username”,因为这些行从一个会话的结尾连接到一个会话的开头接下来,就像下面的那个。 “LW ......”的第一次会议是短暂的,但最终会在下一届会议开始时加入。这个用户就是一个不好的例子。我确实遇到了另一个在午夜过后登录的用户,因此他们的会话以几GB结束,然后他们在同一日历日有另一个会话,所以在下一个会话开始时有一个长的负斜线到“0 MB”。
我有这个图非常接近我想要它。
有两件事我想改变。
首先,我希望x轴在午夜开始,在接下来的午夜结束。当没有人连接时我不想要差距。一些scale_x_...
添加剂似乎适用,但它们在不同日期之间没有明显的效果,有时x轴标签每天都不同,例如列出HH:MM的月和日,以及另一个仅列出的HH:MM。
其次,我希望每个会话都有自己的颜色标识,但我希望图例显示会话的用户名,而不是SessionId值。我不确定如果可能的话,如何更改Legend的值。我使用ggrepel::geom_label_repel
为每个不同的会话生成标签,并且我paste
d用户名,使用的总数据(下载和上传的总和),换行符和“SessionId”的最后四位数字。旁注,我使用mutate
创建“SessionIdFac”作为“SessionId”的因子,因为使用color=SessionId
,其中“SessionId”是一个int,在图例中创建一个连续着色的颜色值。
理想情况下,我在每个会话的图例中都有用户名,例如蓝色矩形示例。我可以选择红色矩形部分,其中最后四位用stringr
包围。
这是完整的脚本。
require(RMySQL)
require(tidyverse)
require(stringr)
con = dbConnect(MySQL(),
user = "OpenVpnBandwidthUsage",
password = "OpenVpnBandwidthUsage",
dbname = "OvpnDb",
host = "172.16.2.100")
on.exit(dbDisconnect(con))
(DateOfVpnTransactions = Sys.Date()-7)
SqlStatement = paste(sep='',
"select " ,
"username , " ,
"IP , " ,
"DateSessionStart , " ,
"TimeSessionStart ," ,
"SessionId ," ,
"DateLastUpdate ," ,
"TimeLastUpdate," ,
"UserUploaded + UserDownloaded as 'TotalBandwidth' " ,
"from Bandwidth " ,
"where DateLastUpdate = '" , DateOfVpnTransactions , "' " ,
"order by DateLastUpdate , TimeLastUpdate , username;"
) ; SqlStatement
results = dbSendQuery(con, SqlStatement)
data = fetch(results , n=-1)
huh = dbHasCompleted(results)
dbClearResult(results)
dbDisconnect(con)
EndpointLabels = data %>%
group_by(SessionId) %>%
mutate(label = if_else(TimeLastUpdate == max(TimeLastUpdate), paste(sep='', username, ': ', TotalBandwidth, ' MB', '\n[', str_sub(SessionId,-4), ']'), NA_character_)) %>%
as.data.frame() %>%
select(label)
DATA = data %>%
mutate(
label_flag = EndpointLabels$label,
username = as.factor(username),
IP = as.factor(IP),
SessionIdFac = as.factor(SessionId),
DateLastUpdate = as.Date(DateLastUpdate),
DateTimeLastUpdate = as.POSIXct(paste(DateLastUpdate, TimeLastUpdate), tz='EST')
)
(MaxData=max(DATA$TotalBandwidth))
cat('Start:' , '\t', format(as.POSIXct(paste(DateOfVpnTransactions, '00:00:00')), '%D %r'))
cat('End:' , '\t', format(as.POSIXct(paste(DateOfVpnTransactions, '23:59:59')), '%D %r'))
DATA %>%
ggplot(aes(x=DateTimeLastUpdate, y=TotalBandwidth)) +
geom_line(aes(color=SessionIdFac), show.legend = TRUE) +
geom_point(aes(color=SessionIdFac), show.legend = TRUE) +
ggrepel::geom_label_repel(aes(label=label_flag), na.rm=TRUE) +
labs(
title = 'OpenVPN Bandwidth usage',
subtitle = 'Separated by discrete session',
x = 'Time of Day',
y = 'Bandwidth used',
color = 'Session'
) +
theme(axis.text.x = element_text(angle = 90 , hjust = 1))
ggsave(paste(sep='', DateOfVpnTransactions, '.png'), device='png', path='c:\\temp\\', width=8, height=5)
编辑:包括一些请求的信息。
DATA %>% str ; DATA %>% head(20) ; DATA %>% tail(20)
'data.frame': 569 obs. of 11 variables:
$ username : Factor w/ 3 levels "cr...","rg...",..: 3 2 3 2 3 2 2 3 3 2 ...
$ IP : Factor w/ 3 levels "1.2.3.158",..: 1 3 1 3 1 3 3 1 1 3 ...
$ DateSessionStart : chr "2019-03-21" "2019-03-21" "2019-03-21" "2019-03-21" ...
$ TimeSessionStart : chr "21:01:00" "22:14:39" "21:01:00" "22:14:39" ...
$ SessionId : int 1553216460 1553220879 1553216460 1553220879 1553216460 1553220879 1553220879 1553216460 1553216460 1553220879 ...
$ DateLastUpdate : Date, format: "2019-03-22" "2019-03-22" "2019-03-22" "2019-03-22" ...
$ TimeLastUpdate : chr "00:00:44" "00:00:53" "00:01:50" "00:01:53" ...
$ TotalBandwidth : num 140 2 140 2 140 2 2 140 140 2 ...
$ label_flag : chr NA NA NA NA ...
$ SessionIdFac : Factor w/ 7 levels "1553216460","1553220879",..: 1 2 1 2 1 2 2 1 1 2 ...
$ DateTimeLastUpdate: POSIXct, format: "2019-03-22 00:00:44" "2019-03-22 00:00:53" "2019-03-22 00:01:50" "2019-03-22 00:01:53" ...
username IP DateSessionStart TimeSessionStart SessionId DateLastUpdate TimeLastUpdate TotalBandwidth label_flag SessionIdFac DateTimeLastUpdate
1 rs... 1.2.3.158 2019-03-21 21:01:00 1553216460 2019-03-22 00:00:44 140 <NA> 1553216460 2019-03-22 00:00:44
2 rg... 2.3.4.242 2019-03-21 22:14:39 1553220879 2019-03-22 00:00:53 2 <NA> 1553220879 2019-03-22 00:00:53
3 rs... 1.2.3.158 2019-03-21 21:01:00 1553216460 2019-03-22 00:01:50 140 <NA> 1553216460 2019-03-22 00:01:50
4 rg... 2.3.4.242 2019-03-21 22:14:39 1553220879 2019-03-22 00:01:53 2 <NA> 1553220879 2019-03-22 00:01:53
5 rs... 1.2.3.158 2019-03-21 21:01:00 1553216460 2019-03-22 00:02:50 140 <NA> 1553216460 2019-03-22 00:02:50
6 rg... 2.3.4.242 2019-03-21 22:14:39 1553220879 2019-03-22 00:02:54 2 <NA> 1553220879 2019-03-22 00:02:54
7 rg... 2.3.4.242 2019-03-21 22:14:39 1553220879 2019-03-22 00:03:55 2 <NA> 1553220879 2019-03-22 00:03:55
8 rs... 1.2.3.158 2019-03-21 21:01:00 1553216460 2019-03-22 00:03:55 140 <NA> 1553216460 2019-03-22 00:03:55
9 rs... 1.2.3.158 2019-03-21 21:01:00 1553216460 2019-03-22 00:04:40 140 <NA> 1553216460 2019-03-22 00:04:40
10 rg... 2.3.4.242 2019-03-21 22:14:39 1553220879 2019-03-22 00:04:55 2 <NA> 1553220879 2019-03-22 00:04:55
11 rs... 1.2.3.158 2019-03-21 21:01:00 1553216460 2019-03-22 00:05:50 140 <NA> 1553216460 2019-03-22 00:05:50
12 rg... 2.3.4.242 2019-03-21 22:14:39 1553220879 2019-03-22 00:05:56 2 <NA> 1553220879 2019-03-22 00:05:56
13 rs... 1.2.3.158 2019-03-21 21:01:00 1553216460 2019-03-22 00:06:55 140 <NA> 1553216460 2019-03-22 00:06:55
14 rg... 2.3.4.242 2019-03-21 22:14:39 1553220879 2019-03-22 00:06:57 2 <NA> 1553220879 2019-03-22 00:06:57
15 rs... 1.2.3.158 2019-03-21 21:01:00 1553216460 2019-03-22 00:07:52 140 <NA> 1553216460 2019-03-22 00:07:52
16 rg... 2.3.4.242 2019-03-21 22:14:39 1553220879 2019-03-22 00:07:58 2 <NA> 1553220879 2019-03-22 00:07:58
17 rs... 1.2.3.158 2019-03-21 21:01:00 1553216460 2019-03-22 00:08:55 140 <NA> 1553216460 2019-03-22 00:08:55
18 rg... 2.3.4.242 2019-03-21 22:14:39 1553220879 2019-03-22 00:08:58 2 <NA> 1553220879 2019-03-22 00:08:58
19 rs... 1.2.3.158 2019-03-21 21:01:00 1553216460 2019-03-22 00:09:54 140 <NA> 1553216460 2019-03-22 00:09:54
20 rg... 2.3.4.242 2019-03-21 22:14:39 1553220879 2019-03-22 00:09:58 2 <NA> 1553220879 2019-03-22 00:09:58
550 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 11:51:51 376 <NA> 1553258874 2019-03-22 11:51:51
551 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 11:52:52 376 <NA> 1553258874 2019-03-22 11:52:52
552 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 11:53:55 380 <NA> 1553258874 2019-03-22 11:53:55
553 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 11:54:55 383 <NA> 1553258874 2019-03-22 11:54:55
554 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 11:55:55 386 <NA> 1553258874 2019-03-22 11:55:55
555 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 11:56:55 388 <NA> 1553258874 2019-03-22 11:56:55
556 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 11:57:55 391 <NA> 1553258874 2019-03-22 11:57:55
557 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 11:58:55 395 <NA> 1553258874 2019-03-22 11:58:55
558 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 11:59:55 395 <NA> 1553258874 2019-03-22 11:59:55
559 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:00:55 395 <NA> 1553258874 2019-03-22 12:00:55
560 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:01:56 395 <NA> 1553258874 2019-03-22 12:01:56
561 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:02:55 396 <NA> 1553258874 2019-03-22 12:02:55
562 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:03:56 400 <NA> 1553258874 2019-03-22 12:03:56
563 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:04:56 412 <NA> 1553258874 2019-03-22 12:04:56
564 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:05:56 418 <NA> 1553258874 2019-03-22 12:05:56
565 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:06:56 419 <NA> 1553258874 2019-03-22 12:06:56
566 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:07:56 420 <NA> 1553258874 2019-03-22 12:07:56
567 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:08:56 423 <NA> 1553258874 2019-03-22 12:08:56
568 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:09:56 426 <NA> 1553258874 2019-03-22 12:09:56
569 cr... 4.5.6.150 2019-03-22 08:47:54 1553258874 2019-03-22 12:10:56 427 cr...: 427 MB\n[8874] 1553258874 2019-03-22 12:10:56
dput(DATA),按摩以匹配上面的数据。
structure(list(
username = structure(c(3L, 2L, 3L, 2L, 3L, 2L, 2L, 3L, 3L, 2L, 3L, 2L, 3L, 2L,
3L, 2L, 3L, 2L, 3L, 2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L,
1L, 1L, 1L, 1L, 1L, 1L), .Label = c("cr...", "rg...", "rs..."), class = "factor"),
IP = structure(c(1L, 3L, 1L, 3L, 1L, 3L, 3L, 1L, 1L, 3L, 1L, 3L, 1L, 3L, 1L, 3L,
1L, 3L, 1L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L,
2L, 2L, 2L, 2L), .Label = c("108.236.141.158", "24.101.215.15", "71.72.44.242"),
class = "factor"),
DateSessionStart = c("2019-03-21", "2019-03-21", "2019-03-21", "2019-03-21",
"2019-03-21", "2019-03-21", "2019-03-21", "2019-03-21", "2019-03-21",
"2019-03-21", "2019-03-21", "2019-03-21", "2019-03-21", "2019-03-21",
"2019-03-21", "2019-03-21", "2019-03-21", "2019-03-21", "2019-03-21",
"2019-03-21", "2019-03-22", "2019-03-22", "2019-03-22", "2019-03-22",
"2019-03-22", "2019-03-22", "2019-03-22", "2019-03-22", "2019-03-22",
"2019-03-22", "2019-03-22", "2019-03-22", "2019-03-22", "2019-03-22",
"2019-03-22", "2019-03-22", "2019-03-22", "2019-03-22", "2019-03-22",
"2019-03-22"),
TimeSessionStart = c("21:01:00", "22:14:39", "21:01:00", "22:14:39", "21:01:00",
"22:14:39", "22:14:39", "21:01:00", "21:01:00", "22:14:39", "21:01:00",
"22:14:39", "21:01:00", "22:14:39", "21:01:00", "22:14:39", "21:01:00",
"22:14:39", "21:01:00", "22:14:39", "08:47:54", "08:47:54", "08:47:54",
"08:47:54", "08:47:54", "08:47:54", "08:47:54", "08:47:54", "08:47:54",
"08:47:54", "08:47:54", "08:47:54", "08:47:54", "08:47:54", "08:47:54",
"08:47:54", "08:47:54", "08:47:54", "08:47:54", "08:47:54"),
SessionId = c(1553216460L, 1553220879L, 1553216460L, 1553220879L, 1553216460L,
1553220879L, 1553220879L, 1553216460L, 1553216460L, 1553220879L, 1553216460L,
1553220879L, 1553216460L, 1553220879L, 1553216460L, 1553220879L, 1553216460L,
1553220879L, 1553216460L, 1553220879L, 1553258874L, 1553258874L, 1553258874L,
1553258874L, 1553258874L, 1553258874L, 1553258874L, 1553258874L, 1553258874L,
1553258874L, 1553258874L, 1553258874L, 1553258874L, 1553258874L, 1553258874L,
1553258874L, 1553258874L, 1553258874L, 1553258874L, 1553258874L),
DateLastUpdate = structure(c(17977, 17977, 17977, 17977, 17977, 17977, 17977,
17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977,
17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977,
17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977,
17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977, 17977,
17977, 17977, 17977), class = "Date"),
TimeLastUpdate = c("00:00:44", "00:00:53", "00:01:50", "00:01:53", "00:02:50",
"00:02:54", "00:03:55", "00:03:55", "00:04:40", "00:04:55", "00:05:50",
"00:05:56", "00:06:55", "00:06:57", "00:07:52", "00:07:58", "00:08:55",
"00:08:58", "00:09:54", "00:09:58", "11:51:51", "11:52:52", "11:53:55",
"11:54:55", "11:55:55", "11:56:55", "11:57:55", "11:58:55", "11:59:55",
"12:00:55", "12:01:56", "12:02:55", "12:03:56", "12:04:56", "12:05:56",
"12:06:56", "12:07:56", "12:08:56", "12:09:56", "12:10:56"),
TotalBandwidth = c(140, 2, 140, 2, 140, 2, 2, 140, 140, 2, 140, 2, 140, 2, 140,
2, 140, 2, 140, 2, 376, 376, 380, 383, 386, 388, 391, 395, 395, 395, 395, 396,
400, 412, 418, 419, 420, 423, 426, 427),
label_flag = c(NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA,
NA, NA, NA, "cr...: 427 MB\n[8874]"),
SessionIdFac = structure(c(1L, 2L, 1L, 2L, 1L, 2L, 2L, 1L, 1L, 2L, 1L, 2L, 1L,
2L, 1L, 2L, 1L, 2L, 1L, 2L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L, 7L,
7L, 7L, 7L, 7L, 7L, 7L, 7L), .Label = c("1553216460", "1553220879", "1553239153", "1553240262", "1553244013",
"1553258796", "1553258874"), class = "factor"),
DateTimeLastUpdate = structure(c(1553230844, 1553230853, 1553230910, 1553230913,
1553230970, 1553230974, 1553231035, 1553231035, 1553231080, 1553231095,
1553231150, 1553231156, 1553231215, 1553231217, 1553231272, 1553231278,
1553231335, 1553231338, 1553231394, 1553231398, 1553273511, 1553273572,
1553273635, 1553273695, 1553273755, 1553273815, 1553273875, 1553273935,
1553273995, 1553274055, 1553274116, 1553274175, 1553274236, 1553274296,
1553274356, 1553274416, 1553274476, 1553274536, 1553274596, 1553274656),
class = c("POSIXct", "POSIXt"), tzone = "EST")), class = "data.frame",
row.names = c(NA, -569L))
对于你的第一个问题,我会尝试expand_limits()
如果你只有一个时间列,那么这样的东西应该工作:
ggplot(...) +
geom_point(...) +
expand_limits(x =c(hms::as.hms("00:00:00"),hms::as.hms("23:59:00")))
或者,您需要定义限制的日期时间。
以下是使用用户名标记会话的两种选择
# create a named vector for the legend
user <- user_tmp %>% pull(username)
names(user) <- user_tmp$SessionId
# alternative one multiple days in a chart
# own column for times needs to be converted into a time
DATA <- DATA %>%
mutate(TimeLastUpdate = hms::as.hms(TimeLastUpdate))
# alternative one plot with times column
DATA %>%
ggplot(aes(x = TimeLastUpdate, y = TotalBandwidth, color =
SessionIdFac)) +
geom_line() +
expand_limits(x =c(hms::as.hms("00:00:00"),hms::as.hms("23:59:00"))) + #expand limits on the time
scale_color_discrete(labels = user) # labels the sessions with the user name
# alternative 2 plotting one day with datetime column
DATA %>%
filter(DateLastUpdate == "2019-03-22") %>% # filter on the day
ggplot(aes(x = DateTimeLastUpdate, y = TotalBandwidth, color = SessionIdFac )) +
geom_line() +
expand_limits(x = c(as.POSIXct("2019-03-22 00:00:00"),
as.POSIXct("2019-03-22 23:59:00"))) + # expand limits for the day
scale_color_discrete(label = user) # label the sessions with user name