2013-12-16 44 views
3

我試圖自動化JMP所做的一個過程(分析 - >分佈,輸入列A作爲「Y值」,使用後續列​​作爲「權重」值)。在JMP中,您必須一次完成一列 - 我想使用Python循環遍歷所有列,並創建一個數組,例如顯示每列的中位數。例如,如果質量數組爲[0,10,20,30],且列1的權重數組爲[30,191,9,0],則質量數組的加權中值應該爲但是,我不確定如何得出這個答案。NumPy或SciPy來計算加權中位數

到目前爲止我

  1. 導入示出的權重爲陣列的CSV,掩蔽的0值,並且
  2. 創建的「Y值」相同的形狀和尺寸與陣列權重數組(113x32)。我不完全確定我需要這樣做,但認爲它比加權循環更容易。

我不確定究竟該從哪裏出發。基本上,「Y值」是一個質量範圍,數組中的所有列表示爲每個質量找到的數據點的數量。我需要根據他們的報告頻率找到中位數量。

我不是Python或統計學的專家,所以如果我省略了任何有用的細節,請告訴我!

更新:這裏是爲了什麼我迄今所做的一些代碼:

#Boilerplate & Import files 
import csv 
import scipy as sp 
from scipy import stats 
from scipy.stats import norm 
import numpy as np 
from numpy import genfromtxt 
import pandas as pd 
import matplotlib.pyplot as plt 

inputFile = '/Users/cl/prov.csv' 
origArray = genfromtxt(inputFile, delimiter = ",") 
nArray = np.array(origArray) 
dimensions = nArray.shape 
shape = np.asarray(dimensions) 

#Mask values ==0 
maTest = np.ma.masked_equal(nArray,0) 

#Create array of masses the same shape as the weights (nArray) 
fieldLength = shape[0] 
rowLength = shape[1] 

for i in range (rowLength): 
    createArr = np.arange(0, fieldLength*10, 10) 
    nCreateArr = np.array(createArr) 
    massArr.append(nCreateArr) 
    nCreateArr = np.array(massArr) 
nmassArr = nCreateArr.transpose() 
+0

一些示例輸入\輸出數據會很有幫助,同時也嘗試顯示代碼到目前爲止您已經走了多遠。 – M4rtini

回答

3

我們能做些什麼,如果我理解正確你的問題。是總結觀察,除以2會給我們觀察數字對應的中位數。從那裏我們需要弄清楚這個數字是什麼意思。

這裏的一個竅門是用np.cumsum來計算觀察和。這給了我們一個運行累積總和。

實施例:
np.cumsum([1,2,3,4]) -> [ 1, 3, 6, 10]
每個元素是所有先前元件和本身的總和。我們在這裏有10個觀察。所以平均值將是第5次觀察。 (通過將最後一個元素除以2得到5)。
現在看cumsum結果,我們可以很容易地看到,必須是第二和第三元素(觀察3和6)之間的觀察。

所以我們需要做的是找出中位數(5)適合的指數。
np.searchsorted完全符合我們的需求。它會找到將元素插入數組的索引,以便它保持排序。

代碼做到這一點,像這樣:

import numpy as np 
#my test data 
freq_count = np.array([[30, 191, 9, 0], [10, 20, 300, 10], [10,20,30,40], [100,10,10,10], [1,1,1,100]]) 

c = np.cumsum(freq_count, axis=1) 
indices = [np.searchsorted(row, row[-1]/2.0) for row in c] 
masses = [i * 10 for i in indices] #Correct if the masses are indeed 0, 10, 20,... 

#This is just for explanation. 
print "median masses is:", masses 
print freq_count 
print np.hstack((c, c[:, -1, np.newaxis]/2.0)) 

輸出將是:

median masses is: [10 20 20 0 30] 
[[ 30 191 9 0] <- The test data 
[ 10 20 300 10] 
[ 10 20 30 40] 
[100 10 10 10] 
[ 1 1 1 100]] 
[[ 30. 221. 230. 230. 115. ] <- cumsum results with median added to the end. 
[ 10. 30. 330. 340. 170. ]  you can see from this where they fit in. 
[ 10. 30. 60. 100. 50. ] 
[ 100. 110. 120. 130. 65. ] 
[ 1.  2.  3. 103. 51.5]] 
+0

非常感謝您的解答!我正在接近但尚未完成。我認爲我沒有把我的問題說清楚 - 基本上,中位數應該總是一個在羣衆範圍內的數字 - [30,191,9,0]的頻率與羣衆[0,10,20,30 ](即0-10範圍內的質量出現30次,10-20的質量出現191次,等等)。上面的答案看起來像我正在獲得頻率計數的中位數,對吧? – Car

+0

是的,它找到頻率計數的中位數,然後將其與羣衆聯繫起來。使用質量範圍與頻率計數的要素直接相關。你是否需要它來確定真正的中位數或包含中位數的範圍?這將找到包含中位數的範圍。 – M4rtini

+0

你可以嘗試給出更多的輸入,輸出例子。或者檢查我使用的「測試數據」,並說出輸出的結果。 – M4rtini

1

共享一些代碼,我得到了一個手。這使您可以在Excel電子表格的每一列上運行統計信息。

import xlrd 
import sys 
import csv 
import numpy as np 
import itertools 
from itertools import chain 

book = xlrd.open_workbook('/filepath/workbook.xlsx') 
sh = book.sheet_by_name("Sheet1") 
ofile = '/outputfilepath/workbook.csv' 

masses = sh.col_values(0, start_rowx=1) # first column has mass 
age = sh.row_values(0, start_colx=1) # first row has age ranges 

count = 1 
mass = [] 
for a in ages: 
    age.append(sh.col_values(count, start_rowx=1)) 
    count += 1 

stats = [] 
count = 0  
for a in ages: 
    expanded = [] 
    # create a tuple with the mass vector 

    age_mass = zip(masses, age[count]) 
    count += 1 
    # replicate element[0] for element[1] times 
    expanded = list(list(itertools.repeat(am[0], int(am[1]))) for am in age_mass) 

    # separate into one big list 
    medianlist = [x for t in expanded for x in t] 

    # convert to array and mask out zeroes 
    npa = np.array(medianlist) 
    npa = np.ma.masked_equal(npa,0) 

    median = np.median(npa) 
    meanMass = np.average(npa) 
    maxMass = np.max(npa) 
    minMass = np.min(npa) 
    stdev = np.std(npa) 

    stats1 = [median, meanMass, maxMass, minMass, stdev] 
    print stats1 

    stats.append(stats1) 

np.savetxt(ofile, (stats), fmt="%d")