Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

- Add the possibility to split networks that contain simplified edges (PR #278, 9798d33512dcdf50d3b88a1223fc4913a2a88eeb, 0ed437c14423c1917f1ba470e7e55db4626d380b, 67a6651b94d50cb7c2ab4a74888b0556d607b102, 98ef83158204be2a67b115cb25df5ba375cccf60, 7ec4d83fdeb308a24a350acd808941807b9511f1, 637d62ab70f098f26f241e588a99cdc49d10f56a, 2c70666f128f96a3a573f29a0cbbef14d803d193, 1cbc6fa36859d6db3a7ff4493ef19763e87d2de3, 41788ff029d038969bfc6b5773e919201c5ac595, b042c0dd08e2229514ccd25dee7a119f25b1ab45, 36d23d657f412aa1953c4773076e593273f19d8e, 402c256d9a05e4ffb297d4ea1fc25d0230787bc0, 54af2b19a112070f10d191b98b055482748426a7, 894414a4a970822b9ecd59c0b6c480860707f636, 0fe32a259ef703c2de79135bfa6932a595fdc1c5)
- Add functionality for commit-message content analysis, such as NLP tools including stemming, tokenization, and lemmatization, as well as a function to search for keywords in commit messages and a function to measure the length of the messages (PR #281, 5aa4e4193f0c00095fedf961c6060a5c035ef9c6, 99f0638566c0062b987617bc3fe3ace1db7729ee, e469d3a0cf2881c378469b6ccfea9c204d13f19b, 7d8fd39f164c776921e3fb36daf79256e7be7426, ef689f71f248059cc69be4792ca14ce3b95dcac8, 6e642242a3063663bcc3c7f5cca0650dfebb6bb4, f54439486115cada08dac23864b2f7605edca9ea, dd9246b2f4506d3d58f1c1f37fc198aaaafebb0d)
- Deprecate support for R version 4.0 because of breaking dependencies (PR #281, 3dc91b155b3e0e2a55378592db448606381f902e)
- Add `unlist.timestamps.if.possible` parameter to `get.edgelist.with.timestamps` which allows callers to request a conversion of the timestamps from list to vector if possible, i.e., when there are no simplified edges in the network (PR #289, 39bf1ddc570057fcae093252d7631e13bc0b5a55)

### Changed/Improved

Expand All @@ -22,6 +22,7 @@
- Rename the `list.attributes` parameter in `add.vertex.attribute` and `split.and.add.vertex.attribute` to `flatten.values` with inverted semantics and introduce documentation for it to improve comprehensibility (PR #285, 7dab04a5251d89c9cb286452528ef8b6775a7347)
- Enhance codeface testing data by ensuring that commit ids are unique between proximity and feature data and by adding commit data that includes (1) different commits that touch the same file / function, (2) commits that are authored at the same time by different authors (PR #286, 7481099af109e1897b9e5754beb1c7da9f39ffb9, 3e53285426010cf7bf48fa23daa484f29f80ac78)
- Sort author data by `author.name` instead of `author.id` when reading it from a file (PR #286, 61b538b7cf81c4b6638951bfaf051e376d0986b3)
- Deprecate support for R version 4.0 because of breaking dependencies (PR #281, 3dc91b155b3e0e2a55378592db448606381f902e)

### Fixed

Expand All @@ -30,6 +31,7 @@
- Ensure that POSIXct values are correctly handled in `add.vertex.attribute`, i.e., that they are not converted to numeric values (PR #285, 7dab04a5251d89c9cb286452528ef8b6775a7347, 4924ac23737dec6f915edaeb350a5cbaebbeec79)
- Handle empty edges when constructing commit networks using commit-interaction data (PR #285, d5e1e4801230224e6272cd66873bd43bb7f04a00)
- Correctly retain order of commit and mail data when merging it with PAStA, synchronicity, and commit message data (PR #286, 50b9b68effd49f853b8bcb335676357a854d1f97)
- Fix `get.edgelist.with.timestamps` to work correctly on networks with dates in default (list) format (PR #289, 35b34bf1d5049904d75122ace847debe0d1595f7)

## 5.0

Expand Down
71 changes: 67 additions & 4 deletions tests/test-misc.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
## Copyright 2017-2018 by Claus Hunsen <hunsen@fim.uni-passau.de>
## Copyright 2017-2018 by Thomas Bock <bockthom@fim.uni-passau.de>
## Copyright 2023 by Thomas Bock <bockthom@cs.uni-saarland.de>
## Copyright 2022-2023 by Maximilian Löffler <s8maloef@stud.uni-saarland.de>
## Copyright 2022-2023, 2025 by Maximilian Löffler <s8maloef@stud.uni-saarland.de>
## All Rights Reserved.


Expand All @@ -24,16 +24,19 @@

test_that("Get edgelist augmented with timestamps", {

##
## Artifical network (without unlisting timestamps)
##

## construct network
Comment thread
bockthom marked this conversation as resolved.
edges = list(list("A", "A"), list("D", "C"), list("C", "A"), list("B", "C"))
edges = list(list("A", "A"), list("D", "C"), list("D", "C"), list("B", "C"))
timestamps = c("2016-12-07 15:30:02", "2016-08-07 15:37:02", "2016-07-12 15:59:25", "2016-07-12 15:59:59")
network =
igraph::make_empty_graph(n = 0, directed = TRUE) +
igraph::vertices("A", "B", "C", "D") +
igraph::edges(edges, relation = "mail", date = timestamps)


## get edgelist augmented with timestamps
## get edgelist with timestamps
edgelist = get.edgelist.with.timestamps(network)

## check correctness
Expand All @@ -45,6 +48,66 @@ test_that("Get edgelist augmented with timestamps", {
expect_equal(actual[["to"]], edges[[i]][[2]])
expect_equal(actual[["date"]], timestamps[i])
})

##
## Authentic network (without unlisting timestamps)
##

## make network authentic (dates as POSIXct in lists)
network = igraph::set_edge_attr(network, "date", value = get.date.from.string(timestamps))
network = convert.edge.attributes.to.list(network)

## get edgelist with timestamps (without unlisting timestamps)
edgelist = get.edgelist.with.timestamps(network, unlist.timestamps.if.possible = FALSE)

## check correctness
expect_equal(names(edgelist), c("from", "to", "date"))
expect_equal(nrow(edgelist), 4)
lapply(1:4, function(i) {
actual = edgelist[i, ]
expect_equal(actual[["from"]], edges[[i]][[1]])
expect_equal(actual[["to"]], edges[[i]][[2]])
expect_equal(actual[["date"]], list(get.date.from.string(as.list(timestamps[i]))))
Comment thread
bockthom marked this conversation as resolved.
})

##
## Authentic network (with unlisting timestamps)
##

## get edgelist with timestamps (with unlisting timestamps)
edgelist.unlisted.if.possible = get.edgelist.with.timestamps(network, unlist.timestamps.if.possible = TRUE)

## check correctness
expect_equal(names(edgelist.unlisted.if.possible), c("from", "to", "date"))
expect_equal(nrow(edgelist.unlisted.if.possible), 4)
lapply(1:4, function(i) {
actual = edgelist.unlisted.if.possible[i, ]
expect_equal(actual[["from"]], edges[[i]][[1]])
expect_equal(actual[["to"]], edges[[i]][[2]])
expect_equal(actual[["date"]], get.date.from.string(timestamps[i]))
})

##
## Authentic network (attempt and fail to unlist timestamps)
##

## simplifying edges should make unlisting timestamps impossible
network = simplify.network(network, remove.loops = FALSE)

## get edgelist with timestamps
edgelist = get.edgelist.with.timestamps(network, unlist.timestamps.if.possible = FALSE)
edgelist.unlisted.if.possible = get.edgelist.with.timestamps(network, unlist.timestamps.if.possible = TRUE)

## construct expected result
expected.edges = data.frame(from = c("A", "B", "D"), to = c("A", "C", "C"))
expected.edges[["date"]] = list(as.list(get.date.from.string(timestamps[1])),
as.list(get.date.from.string(timestamps[4])),
as.list(get.date.from.string(c(timestamps[2], timestamps[3]))))

## check correctness
expect_equal(edgelist, expected.edges, info = "Get edgelist with timestamps.")
expect_equal(edgelist.unlisted.if.possible, expected.edges,
info = "Get edgelist with timestamps (attempt to unlist timestamps fails).")
})


Expand Down
36 changes: 25 additions & 11 deletions util-misc.R
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
## Copyright 2018-2019 by Jakob Kronawitter <kronawij@fim.uni-passau.de>
## Copyright 2021 by Niklas Schneider <s8nlschn@stud.uni-saarland.de>
## Copyright 2022 by Jonathan Baumann <joba00002@stud.uni-saarland.de>
## Copyright 2022-2024 by Maximilian Löffler <s8maloef@stud.uni-saarland.de>
## Copyright 2022-2025 by Maximilian Löffler <s8maloef@stud.uni-saarland.de>
## All Rights Reserved.


Expand All @@ -43,18 +43,32 @@ requireNamespace("lubridate") # for date conversion
#' in order to avoid problems accessing it.
#'
#' @param net the given network
#' @param unlist.timestamps.if.possible whether to unlist timestamps if they are given as lists.
#' Unlisting is not possible when \code{net} contains simplified edges.
#' [default: FALSE]
#'
#' @return the new edgelist
get.edgelist.with.timestamps = function(net) {
## get edge list as data.frame
edges = as.data.frame(igraph::as_edgelist(net))
colnames(edges) = c("from", "to")
## get timestamps
dates = igraph::edge_attr(net, "date")
## bind everything together
edges = cbind(edges, date = dates)

return(edges)
get.edgelist.with.timestamps = function(net, unlist.timestamps.if.possible = FALSE) {

## get edge list as data.frame
edges = as.data.frame(igraph::as_edgelist(net))
colnames(edges) = c("from", "to")

## get timestamps
dates = igraph::edge_attr(net, "date")

## unlist timestamps
if (unlist.timestamps.if.possible && is.list(dates)) {
dates.flattened = do.call(base::c, unlist(dates, recursive = FALSE))
Comment thread
bockthom marked this conversation as resolved.
if (nrow(edges) == length(dates.flattened)) {
dates = dates.flattened
}
}

## bind everything together
edges[["date"]] = dates

return(edges)
}


Expand Down
6 changes: 4 additions & 2 deletions util-plot.R
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
## Copyright 2018 by Barbara Eckl <ecklbarb@fim.uni-passau.de>
## Copyright 2018 by Thomas Bock <bockthom@fim.uni-passau.de>
## Copyright 2020-2021, 2025 by Thomas Bock <bockthom@cs.uni-saarland.de>
## Copyright 2024 by Maximilian Löffler <s8maloef@stud.uni-saarland.de>
## Copyright 2024-2025 by Maximilian Löffler <s8maloef@stud.uni-saarland.de>
## All Rights Reserved.


Expand Down Expand Up @@ -167,7 +167,9 @@ plot.get.plot.for.network = function(network, labels = TRUE) {
end = 0.8, begin = 0.05) +

## scale edges (colors and styles)
ggraph::scale_edge_linetype(name = "Relation Types") +
ggplot2::discrete_scale(name = "Relation Types", aesthetics = "edge_linetype", palette = scales::pal_linetype()) +
## BROKEN RIGHT NOW due to bug in scale_linetype() internally invoked by scale_edge_linetype():
# ggraph::scale_edge_linetype(name = "Relation Types") +
ggplot2::discrete_scale(name = "Relations", aesthetics = "edge_colour",
palette = viridis::viridis_pal(option = "viridis", end = 0.8, begin = 0.25)) +
## BROKEN RIGHT NOW due to bug in scale_edge_colour_viridis():
Expand Down
Loading