I have a dataframe( df below) in pandas with several million rows * 20 columns.
And given a pair of values, I'm trying to find if they exist in adjacent columns of df .
eg df looks like
Given pairs of value (a3, b2) , we find they exist in adjacent columns(doesn't have to be in the same row).
For pairs of value (b2, a3) , we don't consider they meet the condition(the shift of column should be to the right).
This can be done using loops for a small dataset, but I have millions of records with 20 columns and lots of pairs to check. Is there any way to compute this efficiently? Thanks!
Here is a base R solution by defining a function isAdjacent
isAdjacent <- function(df,p) {
colnum <- col(df)
diff(sapply(p,function(x) colnum[df==x],USE.NAMES = FALSE))==1
}
where df
is the data.frame, and p
is the pair.
Example
p1 <- c("b1","c2")
p2 <- rev(p1)
p3 <- c("a1","c3")
> isAdjacent(df,p1)
[1] TRUE
> isAdjacent(df,p2)
[1] FALSE
> isAdjacent(df,p3)
[1] FALSE
Data
> dput(df)
structure(list(A = c("a1", "a2", "a3", "a4"), B = c("b1", "b2",
"b3", "b4"), C = c("c1", "c2", "c3", "c4"), D = c("d1", "d2",
"d3", "d4"), E = c("e1", "e2", "e3", "e4"), F = c("f1", "f2",
"f3", "f4"), G = c("g1", "g2", "g3", "g4")), class = "data.frame", row.names = c(NA,
-4L))
Large Data Example (Benchmarking)
df <- setNames(as.data.frame(sapply(letters[1:20], paste0, 1:1e6)), LETTERS[1:20])
p <- c("a1", "c3")
system.time({
isAdjacent <- function(df, p) {
colnum <- col(df)
diff(sapply(p, function(x) colnum[df == x], USE.NAMES = FALSE)) == 1
}
isAdjacent(df, p)
})
# user system elapsed
# 1.03 0.07 1.11
library(data.table)
system.time({
DT <- data.table(VAL = unlist(df), COL = rep(1L:ncol(df), each = nrow(df)), key = "VAL")
isadj <- function(left, right) {
DT[.(left), .(COL = COL + 1L)][DT[.(right)], on = .(COL), nomatch = 0L, .N > 0L]
}
isadj(p[1], p[2])
})
# user system elapsed
# 35.79 1.91 36.24
Using df
in ThomasIsCoding's post, here is an option using data.table
in R:
library(data.table)
DT <- data.table(VAL=unlist(df), COL=rep(1L:ncol(df), each=nrow(df)), key="VAL")
isadj <- function(left, right) {
DT[.(left), .(COL=COL+1L)][DT[.(right)], on=.(COL), nomatch=0L, .N > 0L]
}
isadj("a3", "b2")
#[1] TRUE
isadj("b2", "a3")
#[1] FALSE
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.