Hoppa till innehållet

Modul:Statistik

Från Wikipedia

Dokumentationen för denna modul kan skapas på Modul:Statistik/dok

local p = {}

require "mw.ustring"

-- slumpdragning, väljer ett antal slumpmässigt valda värden ur en mängd, med lika eller olika sannolikhet och med eller utan återläggning
--
-- parametrar
-- ==========
-- värden (obligatorisk): de värden som kan förekomma, åtskilda med kommatecken (eller det som anges av parametern "split").
-- split (frivillig): den sträng som används för att åtskilja de olika värdena i parametern "värden". Om split ej anges används kommatecken.
-- absolutfrekvenser (frivillig): de absoluta frekvenser som de olika värdena har, åtskilda med kommatecken och i samma ordning som värdena
-- relativfrekvenser (frivillig): de relativa frekvenser som de olika värdena har, åtskilda med kommatecken och i samma ordning som värdena
--   Not: endast en av parametrarna absolutfrekvenser och relativfrekvenser får anges. Om inga frekvenser anges får alla värden samma sannolikhet
-- antal (frivillig): det antal värden som funktionen ska returnera, värdena åtskils med "separator". Om antal ej anges returneras endast ett värde
-- återläggning (frivillig): om värdet nej anges dras värdena utan återläggning, om värdet ja eller inget värde anges dras värdena med återläggning
-- separator (frivillig): teckensträng som används att åtskilja flera returvärden. om separator ej anges blir alla returvärden ihoppackade. 
-- kolumner (frivillig): om parametern ges ett värde ersätts separatorn av wikikod för att skapa en tabell med angivet antal kolumner
-- tabellstil (frivillig): om parametern ges ett värde och kolumner används, så används tabellstil för att styra tabellens utseende
-- fastavärden (frivillig): de positioner och värden för de fasta värden som ska ingå i resultatet. De anges som som pos_1, värde_1, pos_2, värde_2, osv 
-- där pos_n anger positionen för det n:te fasta värdet och värde_n anger vilket av värdena i parametern värden som ska finnas där. OBS att värde_n är
-- positionen i listan värden, inte värdet själv.
--
-- Exempel på användning:
-- {{#invoke:Statistik|slumpdragning|värden=A,B,C|absolutfrekvenser=4,2,1|antal=6|kolumner=3|fastavärden=1,1,3,1,5,1|återläggning=nej}}
-- resulterar i 6 värden i tre kolumner där det första, tredje och femte är ett A och de övriga slumpas från de kvarvarande (1 st A, 2 st B och 1 st C)

function p.slumpdragning(frame)
  local res = ""
  local varden = frame.args['värden']
  if (not varden) then return "Parameterfel: Obligatorisk parameter 'värden' saknas!" end
  local split = frame.args['split'] or ","
  local table vardelista = mw.text.split(varden,split,true)
  local absolutfrekvenser = frame.args['absolutfrekvenser']
  local relativfrekvenser = frame.args['relativfrekvenser']
  local aterlaggning = frame.args['återläggning']
  if (not aterlaggning) then aterlaggning = "" end 
  local antal = frame.args['antal']
  if (antal) then antal = tonumber(antal) else antal = 1 end 
  local separator = frame.args['separator'] or ""
  if (absolutfrekvenser) and (relativfrekvenser) then return "Parameterfel: Både absoluta och relativa frekvenser är angivna!" end
  local kolumner = frame.args['kolumner']
  if (kolumner) then antalkolumner = tonumber(kolumner) end
  local tabellstil = frame.args['tabellstil']
  local fastavarden = frame.args['fastavärden']
  local table fasta_varden = {}
  if (fastavarden) then fasta_varden = mw.text.split(fastavarden,",",true) end
  local table posvarde = {}
  for i = 1, #fasta_varden-1, 2 do
  	posvarde[tonumber(fasta_varden[i])] = tonumber(fasta_varden[i+1])
  end
  
  math.randomseed(os.time())
  if (relativfrekvenser) then
      local table relativfrekvenslista = mw.text.split(relativfrekvenser,",",true)
      if (#relativfrekvenslista ~= #vardelista) then return "Parameterfel: Antal frekvenser (" .. #relativfrekvenslista .. ") ej lika med antalet värden (" .. #vardelista .. ")!" end    
      if (kolumner) then 
      	res = res..'{|' 
      	if (tabellstil) then res = res..tabellstil end
      	res = res..'\n'
      end
      for k=1,antal do
      	if (kolumner) and (k % antalkolumner == 1 or antalkolumner == 1) then
      	  res = res..'|-\n'
      	end 
      	if (posvarde[k]) then
            if (kolumner) then res = res..'|' end
            res = res .. vardelista[posvarde[k]]
            if (kolumner) then res = res..'\n' end
            if (k < antal) and not (kolumner) then res = res .. separator end
      	else	
          slumptal = math.random()
          local ackfrekvens = 0
          for i,v in ipairs(relativfrekvenslista) do
            ackfrekvens = ackfrekvens + tonumber(v)
            if (slumptal <= ackfrekvens) then
              if (kolumner) then res = res..'|' end
              res = res .. vardelista[i]
              if (kolumner) then res = res..'\n' end
              if (k < antal) and not (kolumner) then res = res .. separator end
              break
            end
          end
        end
      end
      if (kolumner) then res = res.."|}\n" end
     return res
  end
 
  local table absolutfrekvenslista = {}
  if (absolutfrekvenser) then
      absolutfrekvenslista = mw.text.split(absolutfrekvenser,",",true)
      if (#absolutfrekvenslista ~= #vardelista) then
         return "Parameterfel: Antal frekvenser (" .. #absolutfrekvenslista .. ") ej lika med antalet värden (" .. #vardelista .. ")!"  
      end
  else
    if (aterlaggning == "nej") then return "Parameterfel: Återläggning får ej vara nej utan att absolutfrekvenser är angivna!" end
    for i,v in ipairs(vardelista) do
      absolutfrekvenslista[i] = 1    
    end     
  end
  n = 0
  for i,v in ipairs(absolutfrekvenslista) do n = n + tonumber(v) end
  if (antal > n) and (aterlaggning == "nej") then return "Parameterfel: Antal (" .. antal .. ") större än antal objekt (" .. n .. ")!" end 
  if (kolumner) then 
  	res = res..'{|' 
  	if (tabellstil) then res = res..tabellstil end
   	res = res..'\n'
  end
  for k=1,antal do
    if (posvarde[k]) then
      if (aterlaggning == "nej") then
        absolutfrekvenslista[posvarde[k]] = absolutfrekvenslista[posvarde[k]] - 1
        n = n - 1
      end
    end
  end
  for k=1,antal do
    if (kolumner) and (k % antalkolumner == 1 or antalkolumner == 1) then
      res = res..'|-\n'
    end
  	if (posvarde[k]) then
      if (kolumner) then res = res..'|' end
      res = res .. vardelista[posvarde[k]]
      if (kolumner) then res = res..'\n' end
      if (k < antal) and not (kolumner) then res = res .. separator end
    else
      slumptal = math.random(1,n)
      local ackfrekvens = 0
      for i,v in ipairs(absolutfrekvenslista) do
        absolutfrekvenslista[i] = tonumber(v)   
        ackfrekvens = ackfrekvens + tonumber(v)
        if (slumptal <= ackfrekvens) then
          if (kolumner) then res = res..'|' end
          res = res .. vardelista[i]
          if (kolumner) then res = res..'\n' end
          if (k<antal) and not (kolumner) then res = res .. separator end    
          if (aterlaggning == "nej") then
            absolutfrekvenslista[i] = absolutfrekvenslista[i] - 1
            n = n - 1
          end
          break
        end       
      end
    end    
  end
  if (kolumner) then res = res.."|}\n" end
  return res
end 

return p