Git Product home page Git Product logo

mirtcat's Introduction

mirtCAT

Computerized Adaptive Testing with Multidimensional Item Response Theory

Welcome

Description

Provides tools to generate an HTML interface for creating adaptive and non-adaptive educational and psychological tests using the shiny package. Suitable for applying unidimensional and multidimensional computerized adaptive tests using item response theory methodology.

Examples and Evaluated Help Files

Various examples and worked help files have been compiled using the knitr package to generate HTML output, and are available on the wiki. User contributions are welcome!

Math Table

Installing from Github

To install the development version of this package, use the following code.

#if not installed already on your computer, install devtools
install.packages('devtools')

#load and install the package
library('devtools')
install_github('philchalmers/mirtCAT')

#reload the package
library('mirtCAT')

Bugs and Questions

Bug reports are always welcome and the preferred way to address these bugs is through the Github 'issues'. Feel free to submit issues or feature requests on the site, and I'll address them ASAP. Also, if you have any questions about the package, or IRT in general, then feel free to create a 'New Topic' in the mirt-package Google group. Cheers!

mirtcat's People

Contributors

drvictorvs avatar magnusnordmo avatar philchalmers avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mirtcat's Issues

Multiple Item Blocks?

Is it possible to define multiple item blocks with different options of their respective items? I'd like to assess one questionnaire only on Sundays and they need to have a different input type.

Feature request: Input answer on itemtimer end

Hi!
After a lot of practical use I have observed that not all users understand the answer button functionality, even though this is clearly explained in an introduction. Some users inputs an answers and erroneously waits until the item timer runs out.A great solution to this is to have a logical input that controls the end of item-timer behaviour.

  • T = selected item/written input is used as input when item timer runs out
  • F = failure to press the answer button before item timer runs out results in wrong answer.

I have tried to implement this myself but have not been successful. I cannot seem to understand how mirtCAT selects the answers provided by the user. My attempts either breaks the test or doesn't provide the answer.

Thanks for mirtCAT! It really is terrific.

Sincerely
Magnus

Strange results in simulation

Dear Phil,
first, thanks for your amazing work on mirt and mirtCAT packages, I could not live without them.

I have a question on strange results that I see when using EAP in MCAT simulation. In a nutshell, I see that the administration of items is finished after response to single items. This only happens when EAP is used (MAP and ML are OK. the reason why the test is finished that the SE_theta drops to ridiculously small values (for all dimensions) after response to single item. Below is the descriptive stats on number of administered items from administrating the test to 1000 simulated individuals .

image

You see that this happens basically for every EAP administration.

When I look into the single simulee theta_se_history I see that the SEs dropped to very low numbers after answering only single question, such as in the example below.

image

Do you have any clue why I see what I see? Your kind insights would be much appreciated, thanks for your response in advance.

Kind Regards,
Jan

Error message with "generate.mirt_object" function

Hi Phil,

I'm keep getting the following error message -- Error in 0L:(K[i] - 1L) : NA/NaN argument -- when I ran this code:

mirt_object = generate.mirt_object(my_item_bank, itemtype = 'graded', min_category = rep(0L, length(itemtype)))

My response data ranges from 0 to 3 for each item (total 30 items) and all the item parameters entered is fine.
Could you please let me know the possible cause of this error?

Thank you!

Youngsoon

Per-Item Timer

The new timer looks great (1.10)! Is there any way of displaying a per-item timer? To be clear, I would like to display the remaining time for each individual question/item and not for the test as a whole.

Problems with firstpage customization

I tried to include a firstpage with instructions. I followed "Customize GUI" demo but when I run the code the first page justdoesn´t appear (no problem with lastpage).

css <- readLines('bootstrap.css')
title <- "REDiC"
authors <- "Aprendemos Todos"
firstpage<- list(h2("Bienvenido"), h5("Trata de responder a cada ejercicio.\n
Buena suerte!"))

lastpage <- function(person){
list(h1("Gracias por tu respuesta"))
}

shinyGUI_list <- list(title = title, authors = authors, demographics = demographics,
demographics_inputIDs = c('ID','Fecha','name','edad','gender'), firstpage = firstpage, lastpage = lastpage, css = css)

results <- mirtCAT(df=df, shinyGUI = shinyGUI_list)

Password example fail

Hi Dr. Chalmers!
I noticed that the example documentation wont run as is:

data.frame(user = c('user1','user2'),password = rep('1234',2))

However, it runs fine when password is capitalized:

data.frame(user = c('user1','user2'),Password = rep('1234',2))

The easiest fix is perhaps just to change the documentation? I am not familier with roxygen so i couldnt push the change on github.

  • Magnus

local_pattern doesn't work when df supplied

Hi,

When I try to supply to mirtCAT function both df and local_pattern I have the following message:

Error in command 'person$responses[pick] <- which(test@item_options[[pick]] %in% ':
change has length 0

I can't find any discrepancy between my df and pattern. I try adjusting types of both. I give pattern as numeric matrix etc. nothing works

error

0s treated as success

When matrix with 0s and 1s provided to mirtCAT function as local_pattern 0s are treated as correct answers when examining thetas etc. It's counterintuitive.

Include parameters via URL

Dear Phil,

as discussed in the google group, it would be great if mirtCAT would be able to handle parameters passed to mirtCAT via the URL. An example would be

http://www.link-to-mirtcat.com?ID=XYZ

where XYZ could for example be the participant ID or any other string.

Based on this post, an edit similar to this one
output$parameters <- parseQueryString(session$clientData$url_search)
in the server-part of the app should be enough.

Thanks in advance

Daniel

ML method with insufficient variability

Hi,
using following R code

set.seed(1221)

### loading data
library("ShinyItemAnalysis") 
data(dataMedical)
dataM=dataMedical[,1:100]

### fitting IRT model
library("mirt") 
mod1<-mirt(dataM,1,itemtype = "3PL")

### generating responses
library("mirtCAT")
N<-100
Theta<-matrix(rnorm(N))
responses<-generate_pattern(mod1,Theta=Theta)


### fitting CAT

modMIML<-mirtCAT(mo=mod1,local_pattern = responses,start_item = "MI",
                 method="ML",criteria="MI")

I get following error:

Error in solve.default(estimate$hessian[pick, pick, drop = FALSE]) :
'a' is 0-diml
Error in sqrt(diag(vcov)) : non-numeric argument to mathematical function
Error in if (.Object@stage > 1L && !any(is.nan(diff)) && all(.Object@met_SEM)) .Object@stop_now <- TRUE :
missing value where TRUE/FALSE needed

I assume that it happens due to insufficient variability of some response patterns for maximum likelihood method but from the documentation for mirtCAT() function I would expect using of "MAP" for these respond patterns (fitting CAT for "MAP" works well).

Am I overlooking or misunderstanding something?
Sorry to bother you.
D. T.

Shuffling in new questions into mirtCAT session

Is there a best way to shuffle in questions that were not fit in the mirt model into the mirt session? These questions would not be graded, and instead would be used in the mirt model later when sufficient data has been collected. It seems like using something like the precat argument in the mirtCAT model would not work since the questions are not part of the original mirt model

Error in : invalid assignment for reference class field ‘raw_responses’, should be from class “integer” or a subclass (was class “character”)

I get this in the latest version from git after answering the first question:

Error in : invalid assignment for reference class field ‘raw_responses’, should be from class “integer” or a subclass (was class “character”)
Stack trace (innermost first):
    89: methods:::.setDummyField
    88: <Anonymous>
    87: assign
    86: envRefSetField
    85: $<-
    84: $<-
    83: reactive reactive({
    click <- input$Next
    if (!length(MCE$shinyGUI$firstpage)) 
        click <- click + 1L
    if (click == 0L) {
        return(MCE$shinyGUI$firstpage)
    }
    if (!length(MCE$shinyGUI$demographics)) 
        click <- click + 1L
    if (click == 1L) {
        return(MCE$shinyGUI$demographics)
    }
    if (click == 2L) {
        tmp <- list()
        for (tag in MCE$shinyGUI$demographic_inputIDs) tmp[[length(tmp) + 
            1L]] <- input[[tag]]
        names(tmp) <- MCE$shinyGUI$demographic_inputIDs
        MCE$person$field("demographics", as.data.frame(tmp))
        if (!is.null(MCE$last_demographics)) 
            MCE$person$demographics <- MCE$last_demographics
        if (MCE$shinyGUI$temp_file != "") 
            saveRDS(MCE$person, MCE$shinyGUI$temp_file)
        return(list(h5(MCE$shinyGUI$begin_message)))
    }
    if (click == 3L) 
        MCE$start_time <- proc.time()[3L]
    if (MCE$resume_file) {
        MCE$resume_file <- FALSE
        item <- max(which(!is.na(MCE$person$items_answered)))
        return(list(MCE$shinyGUI$df$Question[[item]], MCE$shinyGUI$questions[[item]]))
    }
    itemclick <- sum(!is.na(MCE$person$items_answered))
    if (click > 2L && !MCE$design@stop_now) {
        if (itemclick >= 1L) {
            pick <- MCE$person$items_answered[itemclick]
            name <- MCE$test@itemnames[pick]
            ip <- input[[name]]
            if (is.null(ip)) 
                ip <- input[[paste0(MCE$invalid_count, ".TeMpInTeRnAl", 
                  name)]]
            if (!is.null(ip)) {
                ip <- as.character(ip)
                MCE$person$raw_responses[pick] <- ip
                if (!is.null(MCE$test@item_options[[pick]])) {
                  MCE$person$responses[pick] <- which(MCE$test@item_options[[pick]] %in% 
                    ip) - 1L
                }
                if (!is.na(MCE$test@item_answers[[pick]]) && 
                  MCE$test@item_class[pick] != "nestlogit") {
                  MCE$person$responses[pick] <- as.integer(ip %in% 
                    MCE$test@item_answers[[pick]])
                }
                MCE$person$item_time[pick] <- proc.time()[3L] - 
                  MCE$start_time - sum(MCE$person$item_time)
                MCE$person$Update.thetas(MCE$design, MCE$test)
                if (MCE$shinyGUI$temp_file != "") 
                  saveRDS(MCE$person, MCE$shinyGUI$temp_file)
                MCE$design <- Update.stop_now(MCE$design, MCE$person)
            }
            else {
                if (MCE$shinyGUI$forced_choice) {
                  MCE$shift_back <- MCE$shift_back + 1L
                  MCE$invalid_count <- MCE$invalid_count + 1L
                  tmp <- lapply(MCE$shinyGUI$df, function(x, 
                    pick) x[pick], pick = pick)
                  tmp <- buildShinyElements(tmp, paste0(MCE$invalid_count, 
                    ".TeMpInTeRnAl", name))
                  return(list(MCE$shinyGUI$df$Question[[pick]], 
                    tmp$questions))
                }
                else {
                  MCE$person$item_time[pick] <- proc.time()[3L] - 
                    MCE$start_time - sum(MCE$person$item_time)
                  MCE$person$Update.thetas(MCE$design, MCE$test)
                  if (MCE$shinyGUI$temp_file != "") 
                    saveRDS(MCE$person, MCE$shinyGUI$temp_file)
                  MCE$design <- Update.stop_now(MCE$design, MCE$person)
                  MCE$person$valid_item[pick] <- FALSE
                }
            }
        }
        MCE$design <- Next.stage(MCE$design, person = MCE$person, 
            test = MCE$test, item = itemclick)
        if (!MCE$design@stop_now) {
            item <- findNextCATItem(person = MCE$person, test = MCE$test, 
                design = MCE$design, start = FALSE)
            MCE$person$items_answered[itemclick + 1L] <- item
            if (MCE$shinyGUI$temp_file != "") 
                saveRDS(MCE$person, MCE$shinyGUI$temp_file)
            return(list(MCE$shinyGUI$df$Question[[item]], MCE$shinyGUI$questions[[item]]))
        }
    }
    if (!MCE$STOP) {
        MCE$STOP <- TRUE
        if (MCE$shinyGUI$temp_file != "") 
            saveRDS(MCE$person, MCE$shinyGUI$temp_file)
        return(MCE$shinyGUI$lastpage(person = MCE$person))
    }
    else {
        if (!is.null(MCE$final_fun)) {
            ret <- mirtCAT_post_internal(person = MCE$person, 
                design = MCE$design)
            MCE$final_fun(person = ret)
        }
        if (MCE$shinyGUI$temp_file != "") 
            file.remove(MCE$shinyGUI$temp_file)
        stopApp()
        return(NULL)
    }
})
    72: dynamicUi
    71: renderUI
    70: func
    69: output$Main
     2: runApp
     1: mirtCAT

Changing listener port and host?

Is there a way to change the IP/host and port that the application listens on? I know how to change this in shiny itself, but not fromt within mirtCAT.

exposure option selects worst items instead of best?!

Hey, I've really been enjoying mirtCAT! One thing I've noticed recently is that the item exposure option doesn't seem to select from the {x} top items meeting a criteria.
For example, if I use the first demo from the mirtCAT docs, with "MI" for criteria, and set the exposure to 2 for each item, then it selects an item that is clearly not one of the top 2.

I've included plots below from a run with exposure set to 2, and also the code I used to run it (it's basically the first example in the mirtCAT help doc). When I look at the item information at each stage of the test, it doesn't seem to match up with what was selected.

image

image

Code for adaptive test

set.seed(1234)
nitems <- 50
itemnames <- paste0('Item.', 1:nitems)
a <- matrix(rlnorm(nitems, .2, .3))
d <- matrix(rnorm(nitems))
dat <- simdata(a, d, 1000, itemtype = 'dich')
mod <- mirt(dat, 1)
coef(mod, simplify=TRUE)

# alternatively, define mo from population values (not run)
pars <- data.frame(a1=a, d=d)
mod2 <- generate.mirt_object(pars, itemtype='2PL')
coef(mod2, simplify=TRUE)

# simple math items
questions <- answers <- character(nitems)
choices <- matrix(NA, nitems, 5)
spacing <- floor(d - min(d)) + 1 #easier items have more variation in the options

for(i in 1:nitems){
    n1 <- sample(1:50, 1)
    n2 <- sample(51:100, 1)
    ans <- n1 + n2
    questions[i] <- paste0(n1, ' + ', n2, ' = ?')
    answers[i] <- as.character(ans)
    ch <- ans + sample(c(-5:-1, 1:5) * spacing[i,], 5)
    ch[sample(1:5, 1)] <- ans
    choices[i, ] <- as.character(ch)
}

df <- data.frame(Question=questions, Option=choices, 
                              Type = 'radio', stringsAsFactors = FALSE)
# include scoring by providing Answer key
df$Answer <- answers

pat <- generate_pattern(mod, Theta = 0, df = df)
res_MI <- mirtCAT(
  df, mod, 
  criteria = 'MI', 
  start_item = 'MI', 
  local_pattern = pat,
  design = list(exposure = rep(2, extract.mirt(mod, 'nitems')))
  )

plot(mod, type = 'infotrace')
plot(res_MI)

Examining selection

Here I sort item information calculated for each estimated theta during the test.
If you filter on, say, information estimates at the 2nd point in the test, the the selected item (item 1) is pretty low on the list.

library(tidyverse)

thetas <- c(res_MI$thetas_history)

item_info <-
  extract.mirt(mod, 'itemnames') %>%
  tibble(item_num = 1:length(.), item_id = .) %>%
  mutate(
    item =  map(item_id, ~ extract.item(mod, .x)),
    info = map(item, ~ tibble(pos = 1:length(thetas), theta = thetas, info = iteminfo(.x, thetas)))
    ) %>%
  unnest(info) %>%
  arrange(pos, desc(info))

item_info %>% filter(pos == 2)      # item 1 is very low on list!

Random freezes when loading mirtCAT

Sometimes, I'm experiencing freezes when loading the library. I have library("mirtCAT") at the beginning of my script, so this library is loaded every time I run the script. This works mostly fine, but every now and then, R freezes at this point, so that I have to interrupt R manually.

Have you ever experienced this or do you have a hypothesis on why this might occur?

Error message "The new_item selected has already been administered"

Dear Phil,

With mirtCAT I have found a very good, comfortable package for carrying out multidimensional CAT. When simulating the execution of multidimensional CAT with the calibration sample using findNextItem and updateDesign, the error message "The new_item selected has already been administered" is output in 4 out of 300 tests, for which there is no apparent reason. Do you perhaps have an explanation for this? I would be happy to send you the CAT script with the MIRT model.

Kind Regards,
Tom

NA shown as explicit option

Good day, I think I found another anomaly on the HTMLOptions. In a regular data frame without any HTMLOption column, I can simply put NA as the value of the option and it will not pop up when running mirtCAT but when I add the HTMLOption and putting NA as one of the option, it converts it as a character, making the NA be explicitly showed as one of the option. Here is a reprex of the problem.

library("mirtCAT")
options(stringsAsFactors = FALSE)

questions <- c("Building CATs with mirtCAT is difficult.",
               "mirtCAT requires a substantial amount of coding.",
               "I would use mirtCAT in my research.")
options <- matrix(c("<b>Strongly Disagree</b>", "Disagree", "Neutral", "Agree", NA),
                  nrow = 3, ncol = 5, byrow = TRUE)

#NA is showing as one of the option
df <- data.frame(Question = questions, Option = options, Type = "radio", HTMLOptions = TRUE)
mirtCAT(df = df)

#No NA as an option
df2 <- data.frame(Question = questions, Option = options, Type = "radio")
mirtCAT(df = df2)

Thanks in advance!

Bugs in the mirtCAT function

Hello Phil,

I have discussed this issue in brief on google group. I dug further for more criteria and I found there are many other criteria combination which are problematic and possible bugs, so I took the liberty of posting the issue here.

Here are the different combinations:

data(LSAT7)

dat=expand.table(LSAT7)

mod <- mirt(dat,1)

  1. start_item = "MLWI" criteria = 'MI', "MLWI", 'MEI', 'MEPV' and 'MPWI'

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MLWI', criteria = 'MI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in rowSums(ll[, tmp]) :
'x' must be an array of at least two dimensions

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MLWI', criteria = 'MLWI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in rowSums(ll[, tmp]) :
'x' must be an array of at least two dimensions

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MLWI', criteria = 'MEI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in rowSums(ll[, tmp]) :
'x' must be an array of at least two dimensions

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MLWI', criteria = 'MEPV',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in rowSums(ll[, tmp]) :
'x' must be an array of at least two dimensions

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MLWI', criteria = 'MPWI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in rowSums(ll[, tmp]) :
'x' must be an array of at least two dimensions

  1. start_item = "MEPV" criteria = 'MI', "MLWI", 'MEI', 'MEPV' and 'MPWI'

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MEPV', criteria = 'MI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in is(object, "DiscreteClass") :
trying to get slot "mo" from an object of a basic class ("NULL") with no slots

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MEPV', criteria = 'MLWI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in is(object, "DiscreteClass") :
trying to get slot "mo" from an object of a basic class ("NULL") with no slots

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MEPV', criteria = 'MEPV',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in is(object, "DiscreteClass") :
trying to get slot "mo" from an object of a basic class ("NULL") with no slots

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MEPV', criteria = 'MEI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in is(object, "DiscreteClass") :
trying to get slot "mo" from an object of a basic class ("NULL") with no slots

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MEPV', criteria = 'MPWI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in is(object, "DiscreteClass") :
trying to get slot "mo" from an object of a basic class ("NULL") with no slots

  1. start_item = "MPWI" criteria = 'MI', "MLWI", 'MEI', 'MEPV' and 'MPWI'

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MPWI', criteria = 'MI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in rowSums(ll[, tmp]) :
'x' must be an array of at least two dimensions

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MPWI', criteria = 'MLWI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in rowSums(ll[, tmp]) :
'x' must be an array of at least two dimensions

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MPWI', criteria = 'MEI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in rowSums(ll[, tmp]) :
'x' must be an array of at least two dimensions

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MPWI', criteria = 'MEPV',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in rowSums(ll[, tmp]) :
'x' must be an array of at least two dimensions

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MPWI', criteria = 'MPWI',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
Error in rowSums(ll[, tmp]) :
'x' must be an array of at least two dimensions

  1. start_item = "MEI" criteria = 'MEPV'

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MEI', criteria = 'MEPV',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)

findNextItem(CATdesign)
[1] 2
CATdesign <- updateDesign(CATdesign, items = c(2), responses = c(1), Theta = 0)
findNextItem(CATdesign)
Error in is(object, "DiscreteClass") :
trying to get slot "mo" from an object of a basic class ("NULL") with no slots

  1. start_item = "MI" criteria = 'MEPV'

CATdesign <- mirtCAT(df=NULL, mod,start_item = 'MI', criteria = 'MEPV',method = "ML" ,design_elements = TRUE, local_pattern = c(1,1,1,1,1), Theta=0)
findNextItem(CATdesign)
[1] 3
CATdesign <- updateDesign(CATdesign, items = c(3), responses = c(1), Theta = 0)
findNextItem(CATdesign)
Error in is(object, "DiscreteClass") :
trying to get slot "mo" from an object of a basic class ("NULL") with no slots

Tempfile won't get deleted

When I set a temp_file and resume_file, this file doesn't get deleted after the CAT session is finished.

Adding an image in question text

I am trying to create a question where the user has to identify something in an image. I've put the image in the standard RShiny "www" folder and set the question text to something like

<span class="question">What is this?</span> <img src="img1.jpg"></img>
But the image doesn't load. Is there a way to put an image in a question?

Outmessage customization/language support

Hi Phil & all,

as already posted in the google group, I have a suggestion for the next version of the package:
Most parts of the mirtCAT GUI can be configured using the shinyGUI, for example title, authors, and instructions. This is very helpful is you want to run mirtCAT in a non english-speaking country. For some reason, this appears to not be the case for the outmessage "please provide a suitable response".

Thus my suggestion to add the outmessage to the customizable aspects in shinyGUI so that the outmessage can be adapted and mirtCAT would be entirely usable in other languages :-)

Thanks in Advance,

Daniel

Can't change ShinyGUI

Following the "Customize GUI" demo, I tried to define my own ShinyGUI list to override the defaults, but they won't change. Is there anything I'm missing?

Problem with doug function

I´m trying to make a mirtCAT with a item bank that i have, the problem is when I used the function dougs because the first item is correct but when I passed to the second item, it stopped, and not pass. Please help me.
Banco de ítems 2.0.xlsx

library(shiny)
library(mirtCAT)
library(mirt)
library(readxl)
library(httr)

Cargar los datos

file_path <- "C:/Users/User/OneDrive/Desktop/Washington/Aplicaciones/7. mirtCAT/Inteligencia/Banco de ítems 2.0.xlsx"
datos_mirt <- read_excel(file_path)

Preparar el DataFrame

df <- data.frame(
ID_ITEM = datos_mirt$ID_ITEM,
Question = paste0('
', datos_mirt$Texto),
Option.1 = datos_mirt$Option1,
Option.2 = datos_mirt$Option2,
Option.3 = datos_mirt$Option3,
Option.4 = datos_mirt$Option4,
Option.5 = datos_mirt$Option5,
Option.6 = datos_mirt$Option6,
Option.7 = datos_mirt$Option7,
Option.8 = datos_mirt$Option8,
ImageURL_Option1 = datos_mirt$ImageURL_Option1,
ImageURL_Option2 = datos_mirt$ImageURL_Option2,
ImageURL_Option3 = datos_mirt$ImageURL_Option3,
ImageURL_Option4 = datos_mirt$ImageURL_Option4,
ImageURL_Option5 = datos_mirt$ImageURL_Option5,
ImageURL_Option6 = datos_mirt$ImageURL_Option6,
ImageURL_Option7 = datos_mirt$ImageURL_Option7,
ImageURL_Option8 = datos_mirt$ImageURL_Option8,
Type = 'good_DOGS',
stringsAsFactors = FALSE
)

Función personalizada para manejar las opciones de tipo 'good_DOGS'

Doug <- function(inputId, df_row) {
choiceNames <- list()
choiceValues <- list()

for (i in 1:8) {
option <- df_row[[paste0("Option.", i)]]
image_url <- df_row[[paste0("ImageURL_Option", i)]]
if (!is.na(option) && option != "" && !is.na(image_url) && image_url != "") {
choiceNames[[i]] <- tags$img(src = image_url, style = "width:100px;")
choiceValues[[i]] <- as.character(i) # Ensure values are strings
}
}

if (length(choiceNames) == 0 || length(choiceValues) == 0) {
stop("Error: No se generaron opciones válidas para el ítem.")
}

list(
h3(HTML(df_row$Question)),
radioButtons(
inputId = inputId,
label = '',
choiceNames = choiceNames,
choiceValues = choiceValues,
selected = ''
)
)
}

Generar el objeto mirt

parameters <- data.frame(a1 = datos_mirt$a, d = datos_mirt$d)
correct_index <- as.numeric(datos_mirt$Correcta)
mirt_object <- generate.mirt_object(parameters, itemtype = "2PL", key = correct_index)

Ejecutar mirtCAT

results <- mirtCAT(
df = df,
mo = mirt_object,
customTypes = list(good_DOGS = Doug),
criteria = 'MI',
design = list(min_SEM = 0.32, max_items = 13), # Ajuste de min_SEM a 0.32 según tus necesidades
shinyGUI = list(
forced_choice = TRUE, # Asegurarnos de que las respuestas sean forzadas
itemtimer = "Item timer: "
)
)

Verificar si se está registrando la respuesta y avanzando

print("Verificar si se está registrando la respuesta y avanzando:")
print(results)
plot(results)

How to use mirtCAT as a module in another shiny app

I tested several functions of the mirtCAT package and found it's great for the survey of IRT studies. I want to use the mirtCAT as one of the function modules in my own shiny app. However, there's no function such as 'modularize_mirtCAT()' to extract ui and server objects. The extract.mirtCAT() and createShinyGUI() are not for this purpose. Is there any possible approach to embed the UI and Server into the following frameworks of the "golem" module?

#' mirt_cat UI Function
#'
#' @description A shiny Module.
#'
#' @param id,input,output,session Internal parameters for {shiny}.
#'
#' @noRd 
#'
#' @importFrom shiny NS tagList 
mod_mirt_cat_ui <- function(id){
  ns <- NS(id)
  tagList(
 
  )
}
    
#' mirt_cat Server Functions
#'
#' @noRd 
mod_mirt_cat_server <- function(id){
  moduleServer( id, function(input, output, session){
    ns <- session$ns
 
  })
}
    
## To be copied in the UI
# mod_mirt_cat_ui("mirt_cat_ui_1")
    
## To be copied in the server
# mod_mirt_cat_server("mirt_cat_ui_1")

Item_time = 0

Hi again!
Have there been changes to item_time lately? It seems that item_time is set to zero. See example.


library("mirtCAT")
options <- matrix(c("Strongly Disagree", "Disagree", "Neutral", "Agree", "Strongly Agree"),
                  nrow = 3, ncol = 5, byrow = TRUE)

questions <- c("Building CATs with mirtCAT is difficult.",
               "Building tests with mirtCAT requires a lot of coding.",
               "I would use mirtCAT in my research.")

df <- data.frame(Question = questions, Option = options, Type = "radio")

results <- mirtCAT(df = df)

results$item_time

Sincerely
Magnus Nordmo

Multiple sessions result in 'please provide valid response'

Dear Phil,

The library you created is awesome, but we're having some trouble using it; we're probably doing something wrong and require some help. We've developed a test using your library, which is working great, tested the responses and so far everything seems exactly like we want - however we've some trouble scaling.

When we host the application on a Shiny R Server we're running into the fact that the package seems to merge sessions (responses of one user, affects the others). Are we doing something wrong?!

Stephen

[Bug] Incorrect MCAT Example

The official example program presented here includes the following logic for generating a multiplication question:

m1 <- sample(1:50, 1)
m2 <- sample(1:50, 1)
ans <- n1 + n2 + m1 * m2
questions[i] <- paste0(m1, " * ", m2, " = ?")

The values of n1 and n2 are arbitrary, leading to an impossible test question such as:
image

The correct answer is 168, but is not listed.

Item selection for polytomous Items

Hi,

I think there is a bug in the item selection mechanism für polytomous items:

# simulate data for a GRM
a <- matrix(rlnorm(20,.2,.3))
diffs <- t(apply(matrix(runif(20*4, .3, 1), 20), 1, cumsum))
diffs <- -(diffs - rowMeans(diffs))
d <- diffs + rnorm(20)
dat <- simdata(a, d, 500, itemtype = 'graded')

# estimate parameters
fit <- mirt(dat, model=mirt.model('F1=1-20'),
            itemtype="graded")

Item selection using maximum Fisher Information works fine:

design <- list(min_SEM = .02, min_items = 10, max_items = 10)
cat1a  <- mirtCAT(mo=fit, local_pattern = dat[1:10,],
                  start_item = 'MI', method="EAP",
                  criteria   = 'MI', design = design)

However, any other criterion (e.g. MPWI, MEI), fails:

cat1b  <- mirtCAT(mo=fit, local_pattern = dat[1:10,],
                  start_item = 'MI', method="EAP",
                  criteria   = 'MPWI', design = design)
Error in .Primitive("+")(0.00447009764530175, 0.00305388243702458, 0.00115289027322516,  : 
  operator needs one or two arguments

Best, Timo

SSL

Is there an easy way to make mirtCAT use an encrypted connection? I would have to do complicated reverse-proxying action with another http server, which gets really annoying when assessing 30 people in parallel.

HTMLoptions only outputs name of column

Here is another problem I've found. It seems that using HTMLOptions gives wrong values on the raw_responses as well as the scored_responses of the Person object after running the mirtCAT function.

library(mirtCAT)
type <- c("radio")
questions <- c("1236 is the correct")
options <- rbind(c("1236", "1238", "1240", "1242", "1244"))
answers <- c("1236")

oneitem <- data.frame(Question = questions, Option = options, Answer = answers,
                      Type = type, stringsAsFactors = FALSE, HTMLOptions = TRUE)

results <- mirtCAT(df = oneitem)

Looking at the results$raw_responses, it outputs only the name of the column instead of the actual raw response of the user. This then scores the item 0 instead of 1 if the correct answer is selected (as seen on results$scored_responses).

Running it without the HTMLOptions column,

oneitem <- data.frame(Question = questions, Option = options, Answer = answers,
                      Type = type, stringsAsFactors = FALSE)

results <- mirtCAT(df = oneitem)

Gives the corrects raw_responses as well as the scored_responses when the correct answer is selected.

Hope this helps in debugging the HTMLOptions. Thanks!

Item timer freezes after 1 minute

The item timer timer freezes after one minute. This happens because of as.numerics (POSIX) default behaviour is to count output minutes after one minute has passed, instead of seconds, which is required in the delta_time function.

E.g.

as.numeric(Sys.time() - (Sys.time() - 50))
and
as.numeric(Sys.time() - (Sys.time() - 62))

Shiny.io Dropbox Issue

I have encountered an issue while following the vignette on using dropbox and shiny.io server: http://philchalmers.github.io/mirtCAT/html/shinyApps.html

I cannot seem to get the results to be uploaded. Both when I run it locally and on the shiny server I get the message that: "Warning: Error in drop_upload: is_existing_file : Some or all of the files specified by file do not exist."

I have double checked my dropbox authorization and everything looks in order. Maybe it has something to do with this: karthik/rdrop2#134

Btw, thank you for creating mirtCAT!

Skjermbilde 2020-03-18 kl  08 31 57

Skjermbilde 2020-03-18 kl  08 23 43

Pass multiple items and responses to updateDesign

Hello!

In the documentation there exists an example where multiple items and responses are passed to a Desgin object as such(Pg. 12):

# determine next item if item 1 and item 10 were answered correctly, and Theta = 0.5
CATdesign <- updateDesign(CATdesign, items = c(1, 10), responses = c(1, 1), Theta = 0.5)
findNextItem(CATdesign)
findNextItem(CATdesign, all_index = TRUE) # all items rank in terms of most optimal

Sadly this does not seem to work, and the later documentation seems to not even include these parameters, instead only allowing a single item and response pair being passed (this can be confirmed by the code itself).

This feature would be really useful for me personally, so I am curious if this was ever intended behavior and if it is planned to ever support it (possibly again?).

Thanks!

No answer = Wrong answer

Greetings Phil!
Currently responses without input are registered as NA. Is it possible to recode missing responses as scored response=FALSE? Without this, mirtCAT does not learn anything from a missing response with no change in theta or theta_SE. From my perspective I would think that no answer/item timer runs out should equal wrong response. What is your view on this?

Here is an example. When i use to code below and provide no input, mirtCAT doesnt change Theta or SE.

library('mirtCAT')
options(stringsAsFactors = FALSE)

# define population IRT parameters
set.seed(1234)
nitems <- 120
itemnames <- paste0("Item.", 1:nitems)
a <- matrix(c(rlnorm(nitems/2, 0.2, 0.3), rnorm(nitems/4, 0, 0.3), numeric(nitems/2),
              rnorm(nitems/4, 0, 0.3), rlnorm(nitems/2, 0.2, 0.3)), nitems)
d <- matrix(rnorm(nitems))
pars <- data.frame(a, d)
colnames(pars) <- c("a1", "a2", "d")
trait_cov <- matrix(c(1, 0.5, 0.5, 1), 2, 2)

# create mirt_object
mod <- generate.mirt_object(pars, itemtype = "2PL", latent_covariance = trait_cov)

# math items definitions addition for one factor and multiplication for the other
questions <- answers <- character(nitems)
options <- matrix("", nitems, 5)
spacing <- floor(d - min(d)) + 1  #easier items have more variation

for (i in 1:nitems) {
  if (i < 31) {
    # addition
    n1 <- sample(1:100, 1)
    n2 <- sample(101:200, 1)
    ans <- n1 + n2
    questions[i] <- paste0(n1, " + ", n2, " = ?")
  } else if (i < 61) {
    # addition and multiplication
    n1 <- sample(1:50, 1)
    n2 <- sample(51:100, 1)
    m1 <- sample(1:10, 1)
    m2 <- sample(1:10, 1)
    ans <- n1 + n2 + m1 * m2
    questions[i] <- paste0(n1, " + ", n2, " + ", m1, " * ", m2, " = ?")
  } else if (i < 91) {
    # multiplication and addition
    n1 <- sample(1:10, 1)
    n2 <- sample(1:10, 1)
    m1 <- sample(1:25, 1)
    m2 <- sample(1:25, 1)
    ans <- n1 + n2 + m1 * m2
    questions[i] <- paste0(m1, " * ", m2, " + ", n1, " + ", n2, " = ?")
  } else {
    # multiplication
    m1 <- sample(1:50, 1)
    m2 <- sample(1:50, 1)
    ans <- n1 + n2 + m1 * m2
    questions[i] <- paste0(m1, " * ", m2, " = ?")
  }
  answers[i] <- as.character(ans)
  ch <- ans + sample(c(-5:-1, 1:5) * spacing[i, ], 5)
  ch[sample(1:5, 1)] <- ans
  options[i, ] <- as.character(ch)
}

shinyGUI = list(time_before_answer = 1)


# load list of items and their answers
df <- data.frame(Question = questions, 
                 shinyGUI = shinyGUI,
                 Option = options, Answer = answers, Type = "radio",
                 Timer = 6)

result <- mirtCAT(df, mod, criteria = 'Drule', start_item = 'Trule',
                  design = list(min_SEM = 0.4, max_items = 5))
print(result)
plot(result)

image

Installation error

Newbie to R:Sorry if issue is not formatted in right format,
facing issue while installing mirtcat package in local PC,any easy way to fix the issue.

R studio Version 1.3.1073

R version:
platform x86_64-w64-mingw32
arch x86_64
os mingw32
system x86_64, mingw32
status
major 4
minor 0.2
year 2020
month 06
day 22
svn rev 78730
language R
version.string R version 4.0.2 (2020-06-22)
nickname Taking Off Again

logs----

install_github('philchalmers/mirtCAT')
Downloading GitHub repo philchalmers/mirtCAT@HEAD
√ checking for file 'C:\Users\Demons\AppData\Local\Temp\RtmpAVFLDI\remotes1d606aca2409\philchalmers-mirtCAT-9d15576/DESCRIPTION' (1.3s)

  • preparing 'mirtCAT': (1.9s)
    √ checking DESCRIPTION meta-information ...
  • cleaning src
  • installing the package to process help pages (770ms)
    -----------------------------------
  • installing source package 'mirtCAT' ...
    ** using staged installation
    ** libs
    "c:/rtools40/mingw64/bin/"g++ -std=gnu++11 -I"C:/PROGRA1/R/R-401.2/include" -DNDEBUG -I'C:/Users/Demons/Documents/R/win-library/4.0/Rcpp/include' -I'C:/Users/Demons/Documents/R/win-library/4.0/RcppArmadillo/include' -O2 -Wall -mfpmath=sse -msse2 -mstackrealign -c CAT_functions.cpp -o CAT_functions.o
    sh: c:/rtools40/mingw64/bin/g++: No such file or directory
    make: *** [C:/PROGRA1/R/R-401.2/etc/x64/Makeconf:229: CAT_functions.o] Error 127
    ERROR: compilation failed for package 'mirtCAT'
  • removing 'C:/Users/Demons/AppData/Local/Temp/RtmpOOwgbx/Rinst6b029235f/mirtCAT'
    -----------------------------------
    ERROR: package installation failed
    Error: Failed to install 'mirtCAT' from GitHub:
    System command 'Rcmd.exe' failed, exit status: 1, stdout + stderr (last 10 lines):
    E> * installing source package 'mirtCAT' ...
    E> ** using staged installation
    E> ** libs
    E> "c:/rtools40/mingw64/bin/"g++ -std=gnu++11 -I"C:/PROGRA1/R/R-401.2/include" -DNDEBUG -I'C:/Users/Demons/Documents/R/win-library/4.0/Rcpp/include' -I'C:/Users/Demons/Documents/R/win-library/4.0/RcppArmadillo/include' -O2 -Wall -mfpmath=sse -msse2 -mstackrealign -c CAT_functions.cpp -o CAT_functions.o
    E> sh: c:/rtools40/mingw64/bin/g++: No such file or directory
    E> make: *** [C:/PROGRA1/R/R-401.2/etc/x64/Makeconf:229: CAT_functions.o] Error 127
    E> ERROR: compilation failed for package 'mirtCAT'
    E> * removing 'C:/Users/Demons/AppData/Local/Temp/RtmpOOwgbx/Rinst6b029235f/mirtCAT'
    E> -----------------------------------
    E> ERROR: package installation failed

Error : object '.MCE' not found

Pls advice:
Listening on http://127.0.0.1:7780
Warning: Error in tagList: object '.MCE' not found
Stack trace (innermost first):
43: tagList
42: attachDependencies
41: bootstrapPage
40: fluidPage
39: ui [/home/peopleanalytics/Desktop/mirtCAT-master/R/ui.R#3]
1: runApp
Error : object '.MCE' not found

MLE at infinity for a variable response pattern

Hi,

Is this normal behavior?

library(CDM) # For data
data = fraction.subtraction.data

library(mirt) # For training
fit = mirt(data, 2)
V <- coef(fit, simplify=TRUE)$items

Output:

               a1          a2          d g u
Item1  -2.9198130  3.53239933  0.1548285 0 1
Item2  -6.2479459  7.37367588  1.2916350 0 1
...

Seems fine. But then:

library(mirtCAT) # For testing
CATdesign <- mirtCAT(NULL, fit, method='ML', criteria='Drule', start_item='Drule', local_pattern=data, design_elements=TRUE)
CATdesign <- updateDesign(CATdesign, items=c(1), response=c(0))
[email protected](CATdesign$design, CATdesign$person, CATdesign$test)
CATdesign <- updateDesign(CATdesign, items=c(2), response=c(1))
[email protected](CATdesign$design, CATdesign$person, CATdesign$test)
CATdesign$person$thetas_history

I get:

            F1          F2
[1,] 0.0000000    0.000000
[2,] 0.3151363   -0.381255
[3,]      -Inf -598.085780

How come? If I remove method='ML' I get a reasonable (MAP) estimate. But shouldn't the MLE exist for such a simple variable response pattern?

Next-Button on lastpage when stopApp = FALSE,

Hi Phil & all,

I have another suggestion regarding the "next"-Button on the lastpage of a mirtCAT.
When hosting the mirtCAT on a remote server, you suggest the following for stopApp:

when hosting an application on a remote server this should be set to FALSE to allow a more graceful completion (in which case the last page will be displayed until the browser tab is closed)

This is understandable and makes sense. However, with this configuration the lastpage of a mirtCAT stays up "forever" and the "next"-Button, which is displayed, is actually nonfunctional (as there is no next page). This is a bit confusing for users, as they may try to press "next" with nothing happening.

Thus I would recommend to hide the "next"-Button on the last page in this configuration. Alternatively it could also be greyed out, contain a (customizable) link to a website, or even a close-tab command.

Thanks in advance,
Daniel

Fast input cancel timer action

Hi Phil! I've found a slight bug that occurs under a particular circumstance. If you use an item timer and press Next before the time required by shinyGUI = list(time_before_answer), the timer stops but doesnt push the test forward. Im looking at the code now but i'm not sure what causes this.

To recreate this bug, you need to press the Next button before the elapsed seconds supplied with time_before_answer.

library(mirtCAT)

df <- data.frame(Questions = c('First is correct','Second is correct'),
                 Options = matrix(c(1,2,3,4,5),ncol = 5,byrow = T),
                 Type = 'radio',
                 Timer = c(10,10),
                 Answer = c(1,2))

shinyGUI = list(time_before_answer = 3,forced_choice = F)

results <- mirtCAT(df = df,shinyGUI = shinyGUI)

Hope you are doing well!

Sincerely
Magnus

The differences in cov matrix result in significant variations in the simulation outcomes of the mirtCAT study.

Hi,
recently I've been conducting multidimensional (seven dimensions) simulation studies using the mirtCAT package. The purpose is to compare the simulated testing conditions with real-life condition to determine their alignment. Depending on the context, I employed both randomly generated cov matrix and cov matrix obtained from the database to generate response data for the participants using these two distinct approaches. And I utilized these two sets of response data separately to do simulate study .

However, I encountered an issue with the results of the simulation study. The significant discrepancy between the two simulations is concerning. Using data generated from a randomly generated cov matrix, only about 37 items were required for the CAT, while using data from a real cov matrix necessitated 88 items. I believe that such a significant difference shouldn't arise solely from differences in cov matrix. Therefore, I am wondering whether the package might encounter issues with certain types of cov matrix?

It would be really helpful if you could assist in checking if there is any issue. Thank you very much.

The following is my code :
``
#####randomly condition#####
N <- 10000

a_params <- item.params$items[, c("a1", "a2", "a3", "a4", "a5", "a6", "a7")]
a_params
d_params <- item.params$items[, c("d1", "d2", "d3", "d4", "d5")]
d_params

mu <- c(0, 0, 0, 0, 0, 0, 0)

set.seed(2023)

matrix_size <- 7

random_cov_matrix <- matrix(runif(matrix_size^2, -1, 1), nrow = matrix_size)
random_cov_matrix <- random_cov_matrix %*% t(random_cov_matrix)
diag(random_cov_matrix) <- 1
random_cov_matrix[random_cov_matrix > 1] <- 1
random_cov_matrix[random_cov_matrix < -1] <- -1
random_cov_matrix <- nearPD(random_cov_matrix, conv.tol = 1e-7, corr = TRUE)$mat
random_cov_matrix <- 0.5 * (random_cov_matrix + t(random_cov_matrix))
random_cov_matrix <- as.matrix(random_cov_matrix)

print(random_cov_matrix)
true.theta <- rmvnorm(N, mean = mu, sigma = random_cov_matrix)

simulated_data <- simdata(a = a_params, d = d_params, N = N, itemtype = 'graded', Theta = true.theta)

design2 = list(min_SEM = c(0.4,0.4,0.4,0.4,0.4,0.4,0.4), max_items = 98)
#CAT simulation
trysim <- mirtCAT(mo = sim, local_pattern = simulated_data , method = 'MAP', criteria = "Trule",
design = design2)

#####real condition#####
mu <- c(0, 0, 0, 0, 0, 0, 0)

true_cov_matrix <- matrix(c(
1.000, 0.126, 0.131, 0.382, 0.581, 0.408, 0.559,
0.126, 1.000, 0.128, 0.416, 0.441, 0.235, 0.191,
0.131, 0.128, 1.000, 0.058, 0.257, 0.183, 0.029,
0.382, 0.416, 0.058, 1.000, 0.381, 0.714, 0.231,
0.581, 0.441, 0.257, 0.381, 1.000, 0.448, 0.531,
0.408, 0.235, 0.183, 0.714, 0.448, 1.000, 0.271,
0.559, 0.191, 0.029, 0.231, 0.531, 0.271, 1.000
), nrow = 7, byrow = TRUE)

print(true_cov_matrix)

true.theta2 <- rmvnorm(N, mean = mu, sigma = true_cov_matrix)

mod2222 <- generate.mirt_object(parameters, itemtype = 'graded', latent_covariance = true_cov_matrix)

responsepattern2 <- simdata(mo = mod2222, Theta = true.theta2)

#CAT simulation
real_sim_Trule <- mirtCAT(mo = mod2222, local_pattern = responsepattern2, method = 'MAP', criteria = "Trule",
design = design2)

real_simitemsanswered <- laply(real_sim_Trule, function(x) length(x$items_answered))
mean(real_simitemsanswered)
``

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.