Skip to content

Commit 2e38d01

Browse files
Merge pull request #105 from R-Computing-Lab/dev_main
character or factor ID variables fix
2 parents 65d4569 + fc988b9 commit 2e38d01

7 files changed

Lines changed: 107 additions & 13 deletions

File tree

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: BGmisc
22
Title: An R Package for Extended Behavior Genetics Analysis
3-
Version: 1.5.1.009
3+
Version: 1.5.2
44
Authors@R: c(
55
person("S. Mason", "Garrison", , "garrissm@wfu.edu", role = c("aut", "cre"),
66
comment = c(ORCID = "0000-0002-4804-6003")),

NEWS.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
* More flexible ID generation for simulatePedigree
33
* Created ped2gen function to extract generation information from pedigree data.frames
44
* Added tests for ped2gen
5+
* Fixed handling of character ID variables leading to a warning in ped2fam
6+
* Added famIDs to phantom parents
57

68
# BGmisc 1.5.1
79
## CRAN submission

R/checkParents.R

Lines changed: 46 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ checkParentIDs <- function(ped, verbose = FALSE, repair = FALSE,
173173
}
174174
}
175175
}
176-
if (addphantoms) {
176+
if (addphantoms==TRUE) {
177177
# Generate new IDs
178178
newIDbase <- if (is.numeric(ped$ID)) max(ped$ID, na.rm = TRUE) + 1 else paste0("phantom-", seq_len(nrow(ped)))
179179
# Initialize a dataframe to store new entries
@@ -196,19 +196,38 @@ checkParentIDs <- function(ped, verbose = FALSE, repair = FALSE,
196196
newID <- if (is.numeric(ped$ID)) newIDbase + added_counter else paste0("phantom-dad-", ped$ID[idx])
197197
added_counter <- added_counter + 1
198198
ped$dadID[idx] <- newID
199+
if ("famID" %in% names(ped)){
200+
newFAMID <- unique(ped$famID[idx])
201+
newFAMID <- newFAMID[!is.na(newFAMID)]
199202

200-
203+
new_entry <- addParentRow(new_entry_base, newID = newID, dadID = NA, momID = NA, sex = inferred_sex, famID = newFAMID)
204+
} else {
201205
new_entry <- addParentRow(new_entry_base, newID = newID, dadID = NA, momID = NA, sex = inferred_sex)
206+
}
202207
new_entries <- rbind(new_entries, new_entry)
203208
}
204209

205210
# Add moms when missing
206-
inferred_sex <- if (length(validation_results$female_var) > 0 && !is.na(validation_results$female_var)) validation_results$female_var else 0
211+
inferred_sex <- if (length(validation_results$female_var) > 0 && !is.na(validation_results$female_var)){
212+
validation_results$female_var
213+
} else {
214+
0
215+
}
216+
207217
for (idx in which(!is.na(ped$dadID) & is.na(ped$momID))) {
208218
newID <- if (is.numeric(ped$ID)) newIDbase + added_counter else paste0("phantom-mom-", ped$ID[idx])
209219
added_counter <- added_counter + 1
210220
ped$momID[idx] <- newID
221+
222+
if ("famID" %in% names(ped)){
223+
newFAMID <- unique(ped$famID[idx])
224+
newFAMID <- newFAMID[!is.na(newFAMID)]
225+
226+
new_entry <- addParentRow(new_entry_base, newID = newID, dadID = NA, momID = NA, sex = inferred_sex, famID = newFAMID)
227+
} else {
228+
211229
new_entry <- addParentRow(new_entry_base, newID = newID, dadID = NA, momID = NA, sex = inferred_sex)
230+
}
212231
new_entries <- rbind(new_entries, new_entry)
213232
}
214233

@@ -300,7 +319,19 @@ addRowlessParents <- function(ped, verbose, validation_results) {
300319
)
301320
inferred_sex <- if ("mom" %in% role) validation_results$female_var else validation_results$male_var
302321

303-
new_entry <- addParentRow(new_entry_base, newID = pid, dadID = NA, momID = NA, sex = inferred_sex)
322+
if("famID" %in% names(ped)){
323+
newFAMID <- unique(ped$famID[which(ped$momID == pid | ped$dadID == pid)])
324+
newFAMID <- newFAMID[!is.na(newFAMID)]
325+
326+
327+
if(length(newFAMID) >1){
328+
newFAMID <- NA
329+
}
330+
331+
new_entry <- addParentRow(new_entry_base, newID = pid, dadID = NA, momID = NA, sex = inferred_sex, famID = newFAMID)
332+
} else {
333+
new_entry <- addParentRow(new_entry_base, newID = pid, dadID = NA, momID = NA, sex = inferred_sex)
334+
}
304335

305336
new_entries <- rbind(new_entries, new_entry)
306337
}
@@ -324,16 +355,24 @@ addRowlessParents <- function(ped, verbose, validation_results) {
324355
#' @param sex The new parent's sex value (e.g., 0 for female, 1 for male, or "F"/"M")
325356
#' @param momID The new parent's mother ID (default is NA)
326357
#' @param dadID The new parent's father ID (default is NA)
358+
#' @param famID The new parent's family ID (default is NA)
327359
#' @return A single-row dataframe for the new parent
328360
addParentRow <- function(template_row, newID, sex,
329361
momID = NA,
330-
dadID = NA) {
362+
dadID = NA,
363+
famID = NA
364+
) {
331365
new_row <- template_row
332366
new_row[] <- NA # set all columns to NA
333367
new_row$ID <- newID
334-
new_row$momID <- NA
335-
new_row$dadID <- NA
368+
new_row$momID <- momID
369+
new_row$dadID <- dadID
336370
new_row$sex <- sex
371+
372+
if ("famID" %in% names(template_row)) {
373+
new_row$famID <- famID
374+
}
337375
# You can add more column initializations here if needed
376+
338377
return(new_row)
339378
}

R/segmentPedigree.R

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,24 @@ ped2fam <- function(ped, personID = "ID",
4444
# Find weakly connected components of graph
4545
wcc <- igraph::components(pg)
4646

47-
fam <- data.frame(
48-
V1 = as.numeric(names(wcc$membership)),
49-
V2 = wcc$membership
50-
)
47+
# Create famID data.frame
48+
# Convert IDs to numeric, with warning if coercion collapses IDs
49+
uniques <- suppressWarnings(unique(as.numeric(names(wcc$membership))))
50+
51+
if (length(uniques) == 1L && is.na(uniques)) {
52+
warning("After converting IDs to numeric, all IDs became NA. This indicates ID coercion collapsed IDs. Please ensure IDs aren't character or factor variables.")
53+
54+
fam <- data.frame(
55+
V1 = names(wcc$membership),
56+
V2 = wcc$membership
57+
)
58+
} else {
59+
fam <- data.frame(
60+
V1 = as.numeric(names(wcc$membership)),
61+
V2 = wcc$membership
62+
)
63+
}
64+
5165
names(fam) <- c(personID, famID)
5266
ped2 <- merge(fam, ped,
5367
by = personID, all.x = FALSE, all.y = TRUE

man/addParentRow.Rd

Lines changed: 3 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/testthat/test-checkParents.R

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ test_that("checksif single parents found correctly in ASOIAF dataset", {
2424
expect_equal(single_dads, length(results$missing_mothers))
2525
repaired_df <- checkParentIDs(df_asoiaf, verbose = FALSE, repair = TRUE, parentswithoutrow = TRUE)
2626
expect_equal(nrow(repaired_df), nrow(df_asoiaf) + single_moms + single_dads)
27+
28+
29+
repaired_phantoms <- checkParentIDs(df_asoiaf, verbose = FALSE, repair = TRUE, addphantoms = TRUE)
30+
expect_equal(nrow(repaired_phantoms), nrow(df_asoiaf) + single_moms + single_dads)
31+
# did it add more famIDs?
32+
expect_true(length(repaired_phantoms$famID[!is.na(repaired_phantoms$famID)]) > length(df_asoiaf$famID[!is.na(df_asoiaf$famID)]))
33+
# do the original famIDs remain unique?
34+
expect_true(length(unique(repaired_phantoms$famID[!is.na(repaired_phantoms$famID)])) == length(unique(df_asoiaf$famID[!is.na(df_asoiaf$famID)])))
35+
2736
})
2837

2938
test_that("verbose checks", {

tests/testthat/test-segmentPedigree.R

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,38 @@
1+
test_that("ped2fam is smart about string ids", {
2+
data(hazard)
3+
ds_num <- ped2fam(hazard, famID = "newFamID")
4+
expect_true(is.numeric(ds_num$ID))
5+
expect_true(is.numeric(ds_num$newFamID))
6+
hazard$ID_og <- hazard$ID
7+
hazard$ID <- paste0("ID", hazard$ID)
8+
hazard$dadID <- paste0("ID", hazard$dadID)
9+
hazard$dadID[hazard$dadID == "IDNA"] <- NA
10+
hazard$momID <- paste0("ID", hazard$momID)
11+
hazard$momID[hazard$momID == "IDNA"] <- NA
12+
expect_warning(ped2fam(hazard, famID = "newFamID"))
13+
ds <- suppressWarnings(ped2fam(hazard, famID = "newFamID"))
14+
tab <- table(ds$famID, ds$newFamID)
15+
expect_true(all(grepl("^ID", ds$ID)))
16+
ds_num_s <- ds_num[order(ds_num$ID), ]
17+
hazard_s <- hazard[order(hazard$ID_og), ]
18+
ds_s <- ds[order(ds$ID_og), ]
19+
expect_equal(ds_num_s$ID, hazard_s$ID_og)
20+
expect_equal(ds_num_s$newFamID, hazard_s$famID)
21+
expect_equal(ds_s$ID, hazard_s$ID)
22+
expect_equal(ds_num_s$newFamID, hazard_s$famID)
23+
expect_equal(ds_num_s$newFamID, ds_s$newFamID)
24+
expect_equal(ds_s$famID, ds_s$newFamID)
25+
})
26+
27+
128
test_that("ped2fam gets the right families for hazard data", {
229
data(hazard)
330
ds <- ped2fam(hazard, famID = "newFamID")
431
tab <- table(ds$famID, ds$newFamID)
532
expect_equal(ds$famID, ds$newFamID)
633
})
734

35+
836
test_that("ped2fam gets the right families for inbreeding data", {
937
data(inbreeding)
1038
ds <- ped2fam(inbreeding, famID = "newFamID")

0 commit comments

Comments
 (0)