Python Orange入門之第一節:數據輸入格式

數據

本節介紹如何在Orange中加載數據。我們還將展示如何探索數據,執行一些基本統計以及如何對數據進行採樣。

數據輸入

Orange可以以原生製表符分隔格式讀取文件,也可以從任何主要標準電子表格文件類型(如CSV和Excel)加載數據。本機格式以帶有要素(列)名稱的標題行開頭。第二個標題行提供屬性類型,可以是連續,離散,時間或字符串。第三個標題行包含用於標識依賴特徵(類),不相關特徵(忽略)或元特徵(元)的元信息。加載和保存數據(io)中提供了更詳細的規範。以下是數據集中的前幾行lenses.tab

age       prescription  astigmatic    tear_rate     lenses
discrete  discrete      discrete      discrete      discrete
                                                    class
young     myope         no            reduced       none
young     myope         no            normal        soft
young     myope         yes           reduced       none
young     myope         yes           normal        hard
young     hypermetrope  no            reduced       none

值是製表符限制的。該數據集具有四個屬性(患者年齡,眼鏡處方,散光概念,淚液產生率信息)和相關的三值因變量編碼鏡片處方(硬性隱形眼鏡,軟性隱形眼鏡,無鏡片) )。功能描述只能使用一個字母,因此該數據集的標題也可以是:

age       prescription  astigmatic    tear_rate     lenses
d         d             d             d             d
                                                    c

表格的其餘部分給出了數據。請注意,上表中有5個實例。對於完整數據集,請檢出或下載lenses.tab到目標目錄。您也可以跳過此步驟,因爲Orange預裝了幾個演示數據集,鏡頭就是其中之一。現在,打開一個python shell,導入Orange並加載數據:

>>> import Orange
>>> data = Orange.data.Table("lenses")
>>>

請注意,對於文件名,不需要後綴,因爲Orange會檢查當前目錄中的任何文件是否爲可讀類型。調用Orange.data.Table創建了一個名爲對象data包含您的數據集和有關鏡頭域的信息:

>>> data.domain.attributes
(DiscreteVariable('age', values=['pre-presbyopic', 'presbyopic', 'young']),
 DiscreteVariable('prescription', values=['hypermetrope', 'myope']),
 DiscreteVariable('astigmatic', values=['no', 'yes']),
 DiscreteVariable('tear_rate', values=['normal', 'reduced']))
>>> data.domain.class_var
DiscreteVariable('lenses', values=['hard', 'none', 'soft'])
>>> for d in data[:3]:
   ...:     print(d)
   ...:
[young, myope, no, reduced | none]
[young, myope, no, normal | soft]
[young, myope, yes, reduced | none]
>>>

以下腳本包含了我們目前所做的所有事情,並列出了前5個數據實例和soft處方:

import Orange
data = Orange.data.Table("lenses")
print("Attributes:", ", ".join(x.name for x in data.domain.attributes))
print("Class:", data.domain.class_var.name)
print("Data instances", len(data))

target = "soft"
print("Data instances with %s prescriptions:" % target)
atts = data.domain.attributes
for d in data:
    if d.get_class() == target:
        print(" ".join(["%14s" % str(d[a]) for a in atts]))

請注意,數據是一個包含域中數據和信息的對象。我們在上面展示瞭如何訪問屬性和類名,但是有更多的信息,包括關於要素類型,分類要素的值集等。

保存數據

數據對象可以保存到文件中:

>>> data.save("new_data.tab")
>>>

這次,我們必須提供文件擴展名來指定輸出格式。原生Orange的數據格式的擴展名爲“.tab”。以下代碼僅使用myope perscription保存數據項:

import Orange
data = Orange.data.Table("lenses")
myope_subset = [d for d in data if d["prescription"] == "myope"]
new_data = Orange.data.Table(data.domain, myope_subset)
new_data.save("lenses-subset.tab")

我們通過傳遞data(data.domain)結構和數據實例子集的信息創建了一個新的數據表。

探索數據域

數據表存儲有關數據實例以及數據域的信息。Domain包含屬性,可選類及其類型的名稱,以及值名稱(如果是分類)。以下代碼:

import Orange

data = Orange.data.Table("imports-85.tab")
n = len(data.domain.attributes)
n_cont = sum(1 for a in data.domain.attributes if a.is_continuous)
n_disc = sum(1 for a in data.domain.attributes if a.is_discrete)
print("%d attributes: %d continuous, %d discrete" % (n, n_cont, n_disc))

print("First three attributes:",
      ", ".join(data.domain.attributes[i].name for i in range(3)))

print("Class:", data.domain.class_var.name)

輸出:

25 attributes: 14 continuous, 11 discrete
First three attributes: symboling, normalized-losses, make
Class: price

Orange的對象通常表現得像Python列表和字典,可以通過功能名稱編制索引或訪問:

print("First attribute:", data.domain[0].name)
name = "fuel-type"
print("Values of attribute '%s': %s" %
      (name, ", ".join(data.domain[name].values)))

上面代碼的輸出是:

First attribute: symboling
Values of attribute 'fuel-type': diesel, gas

數據實例

數據表存儲數據實例(或示例)。這些可以像任何Python列表一樣被索引或遍歷。數據實例可以視爲向量,通過元素索引或通過功能名稱訪問。

import Orange

data = Orange.data.Table("iris")
print("First three data instances:")
for d in data[:3]:
    print(d)

print("25-th data instance:")
print(data[24])

name = "sepal width"
print("Value of '%s' for the first instance:" % name, data[0][name])
print("The 3rd value of the 25th data instance:", data[24][2])

上面的腳本顯示以下輸出:

First three data instances:
[5.100, 3.500, 1.400, 0.200 | Iris-setosa]
[4.900, 3.000, 1.400, 0.200 | Iris-setosa]
[4.700, 3.200, 1.300, 0.200 | Iris-setosa]
25-th data instance:
[4.800, 3.400, 1.900, 0.200 | Iris-setosa]
Value of 'sepal width' for the first instance: 3.500
The 3rd value of the 25th data instance: 1.900

我們上面使用的Iris數據集有四個連續屬性。這是一個計算其平均值的腳本:

average = lambda x: sum(x)/len(x)

data = Orange.data.Table("iris")
print("%-15s %s" % ("Feature", "Mean"))
for x in data.domain.attributes:
    print("%-15s %.2f" % (x.name, average([d[x] for d in data])))

上面的腳本還說明了使用存儲功能的對象索引數據實例; in d[x]variable x是一個Orange對象。這是輸出:

Feature         Mean
sepal length    5.84
sepal width     3.05
petal length    3.76
petal width     1.20

一個稍微複雜但也更有趣的代碼,用於計算每個類的平均值:

average = lambda xs: sum(xs)/float(len(xs))

data = Orange.data.Table("iris")
targets = data.domain.class_var.values
print("%-15s %s" % ("Feature", " ".join("%15s" % c for c in targets)))
for a in data.domain.attributes:
    dist = ["%15.2f" % average([d[a] for d in data if d.get_class() == c])
            for c in targets]
    print("%-15s" % a.name, " ".join(dist))

在這四個特徵中,花瓣寬度和長度看起來對於虹膜的類型非常有區別:

Feature             Iris-setosa Iris-versicolor  Iris-virginica
sepal length               5.01            5.94            6.59
sepal width                3.42            2.77            2.97
petal length               1.46            4.26            5.55
petal width                0.24            1.33            2.03

最後,這是一個快速代碼,用於計算另一個數據集的類分佈:

import Orange
from collections import Counter

data = Orange.data.Table("lenses")
print(Counter(str(d.get_class()) for d in data))

橙色數據集和NumPy的

橙色數據集實際上是包裝的NumPy數組。執行包裝以保留有關功能名稱和值的信息,NumPy數組用於提高與橙色所依賴的不同機器學習工具箱(如scikit-learn)的兼容性。讓我們爲虹膜數據集的前三個數據實例顯示這些數組的值:

>>> data = Orange.data.Table("iris")
>>> data.X[:3]
array([[ 5.1,  3.5,  1.4,  0.2],
       [ 4.9,  3. ,  1.4,  0.2],
       [ 4.7,  3.2,  1.3,  0.2]])
>>> data.Y[:3]
array([ 0.,  0.,  0.])

請注意,我們使用data.X和分別訪問屬性和類的數組data.Y。然後可以通過以下方式有效地計算屬性的平均值:

>>> import np as numpy
>>> np.mean(data.X, axis=0)
array([ 5.84333333,  3.054     ,  3.75866667,  1.19866667])

我們還可以從numpy數組構造一個(無類)數據集:

>>> X = np.array([[1,2], [4,5]])
>>> data = Orange.data.Table(X)
>>> data.domain
[Feature 1, Feature 2]

如果我們想爲屬性提供有意義的名稱,我們需要構建一個合適的數據域:

>>> domain = Orange.data.Domain([Orange.data.ContinuousVariable("lenght"),
                                 Orange.data.ContinuousVariable("width")])
>>> data = Orange.data.Table(domain, X)
>>> data.domain
[lenght, width]

這是另一個例子,這次是構建一個包含數字類和不同類型屬性的數據集:

size = Orange.data.DiscreteVariable("size", ["small", "big"])
height = Orange.data.ContinuousVariable("height")
shape = Orange.data.DiscreteVariable("shape", ["circle", "square", "oval"])
speed = Orange.data.ContinuousVariable("speed")

domain = Orange.data.Domain([size, height, shape], speed)

X = np.array([[1, 3.4, 0], [0, 2.7, 2], [1, 1.4, 1]])
Y = np.array([42.0, 52.2, 13.4])

data = Orange.data.Table(domain, X, Y)
print(data)

運行此腳本會產生:

[[big, 3.400, circle | 42.000],
 [small, 2.700, oval | 52.200],
 [big, 1.400, square | 13.400]

元屬性

通常,我們希望在數據中包含不會用於任何計算(距離估計,建模)的描述性字段,但將用於識別或附加信息。這些被稱爲元屬性,並meta在第三個標題行中標記:

name	hair	eggs	milk	backbone	legs	type
string	d	d	d	d	d	d
meta						class
aardvark	1	0	1	1	4	mammal
antelope	1	0	1	1	4	mammal
bass	0	1	0	1	0	fish
bear	1	0	1	1	4	mammal

元屬性和所有其他(非元)屬性的值在Orange中類似地處理,但存儲在單獨的numpy數組中:

>>> data = Orange.data.Table("zoo")
>>> data[0]["name"]
>>> data[0]["type"]
>>> for d in data:
    ...:     print("{}/{}: {}".format(d["name"], d["type"], d["legs"]))
    ...:
aardvark/mammal: 4
antelope/mammal: 4
bass/fish: 0
bear/mammal: 4
>>> data.X
array([[ 1.,  0.,  1.,  1.,  2.],
       [ 1.,  0.,  1.,  1.,  2.],
       [ 0.,  1.,  0.,  1.,  0.],
       [ 1.,  0.,  1.,  1.,  2.]]))
>>> data.metas
array([['aardvark'],
       ['antelope'],
       ['bass'],
       ['bear']], dtype=object))

Orange.data.Table在爲屬性和類值提供數組之後,可以傳遞元屬性:

from Orange.data import Table, Domain
from Orange.data import ContinuousVariable, DiscreteVariable, StringVariable
import numpy as np

X = np.array([[2.2, 1625], [0.3, 163]])
Y = np.array([0, 1])
M = np.array([["houston", 10], ["ljubljana", -1]])

domain = Domain([ContinuousVariable("population"), ContinuousVariable("area")],
                [DiscreteVariable("snow", ("no", "yes"))],
                [StringVariable("city"), StringVariable("temperature")])
data = Table(domain, X, Y, M)
print(data)

腳本輸出:

[[2.200, 1625.000 | no] {houston, 10},
 [0.300, 163.000 | yes] {ljubljana, -1}

爲了構造一個無類域,我們可以傳遞None類值。

缺少值

考慮以下對美國參議院投票數據集的探索:

>>> import numpy as np
>>> data = Orange.data.Table("voting.tab")
>>> data[2]
[?, y, y, ?, y, ... | democrat]
>>> np.isnan(data[2][0])
True
>>> np.isnan(data[2][1])
False

特定數據實例包括第一個和第四個屬性的缺失數據(用'?'表示)。在原始數據集文件中,默認情況下,缺失值用空格表示。我們現在可以檢查每個屬性並報告未定義此功能的數據實例的比例:

data = Orange.data.Table("voting.tab")
for x in data.domain.attributes:
    n_miss = sum(1 for d in data if np.isnan(d[x]))
    print("%4.1f%% %s" % (100.*n_miss/len(data), x.name))

此腳本輸出的前三行是:

 2.8% handicapped-infants
11.0% water-project-cost-sharing
 2.5% adoption-of-the-budget-resolution

報告具有至少一個缺失值的數據實例數的單行程序是:

>>> sum(any(np.isnan(d[x]) for x in data.domain.attributes) for d in data)
203

數據選擇和採樣

除了數據文件的名稱,Orange.data.Table可以接受數據域和數據項列表並返回新的數據集。這對任何數據子集都很有用:

data = Orange.data.Table("iris.tab")
print("Dataset instances:", len(data))
subset = Orange.data.Table(data.domain,
                           [d for d in data if d["petal length"] > 3.0])
print("Subset size:", len(subset))

代碼輸出:

Dataset instances: 150
Subset size: 99

並從原始數據集繼承數據描述(域)。更改域需要設置新的域描述符。此功能適用於任何類型的功能選擇:

data = Orange.data.Table("iris.tab")
new_domain = Orange.data.Domain(list(data.domain.attributes[:2]),
                                data.domain.class_var)
new_data = Orange.data.Table(new_domain, data)

print(data[0])
print(new_data[0])

我們還可以構建數據集的隨機樣本:

>>> sample = Orange.data.Table(data.domain, random.sample(data, 3))
>>> sample
[[6.000, 2.200, 4.000, 1.000 | Iris-versicolor],
 [4.800, 3.100, 1.600, 0.200 | Iris-setosa],
 [6.300, 3.400, 5.600, 2.400 | Iris-virginica]
]

或隨機抽樣屬性:

>>> atts = random.sample(data.domain.attributes, 2)
>>> domain = Orange.data.Domain(atts, data.domain.class_var)
>>> new_data = Orange.data.Table(domain, data)
>>> new_data[0]
[5.100, 1.400 | Iris-setosa]

Orange數據挖掘庫

導航

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章