2017年12月31日日曜日

The Zen of Python (Python公案)

Pythonの哲学を示す"The Zen of Python by Tim Peters"というものがあることを知りました.
対話型インタープリターに"import this"と入力すると見ることができます.

>>> import this
The Zen of Python, by Tim Peters

Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
>>> 

2017年12月27日水曜日

[Python] モジュール

モジュールのインポートは過去の投稿(例えば前回)でも使用しています.
前回の投稿のモジュールのインポートは,以下の部分で行なっています.
>>> import datetime

モジュールは,関数,クラス,定数などを集めたものです.ちなみに,上記の datetime モジュールは日付や時間に関する操作をまとめたモジュールです.上記のようにモジュールをインポートすると,そのモジュール内の関数,クラスを使うことができます.
以下の例のように,datetime モジュールをインポートして,datetimeモジュール内のdate クラスを使用します.
>>> import datetime
>>> d = datetime.date(2017, 12, 27) # Creating a data object
>>> d
datetime.date(2017, 12, 27)

同じクラスを多用する場合は,毎回 datetime.data として参照するのが面倒と感じる場合は,以下のように from ... import ... 構文を使用することもできます.
>>> from datetime import date
>>> d = date(2017, 12, 27)
>>> d
datetime.date(2017, 12, 27)
この例のように,インポートしたいクラス(関数,定数も同様)を指定してインポートすると,それ以降はモジュール名を指定しなくてもそのクラス(関数,定数)を使用することができるようになります.

モジュール内の全てをインポートするには以下のようにすることもできますが,複数のモジュールをインポートした際には,名前の衝突に気づかないことがあります.
>>> from datetime import *
>>> d = date(2017, 12, 27)
>>> d
datetime.date(2017, 12, 27)

上記の理由で,全てをインポートすることは推奨されていないので,以下のように長いモジュール名を使わないようにするために,import ... as ... 構文を使用することができます.
>>> import datetime as dt
>>> d = dt.date(2017, 12, 27)
>>> d
datetime.date(2017, 12, 27)
1行目でdatetimeモジュールをdtとしてインポートして,それ以降はdt はdatetime モジュールを指します.この昨日は,名前の衝突を避けてコードを短くできるというメリットがありますが,乱用すると可読性が低下するデメリットがあります.

モジュールの作成
独自にモジュールを作成する場合は,特に明示的に宣言する必要はありません..pyファイルにクラス,関数,および定数などを記述すると,自動的にモジュールとして扱うことができるようになります.以下はその例です.

まずは,以下のコードを作成してmod1.pyという名前で保存します.
def hello():
    return "Hello!"

続いて,REPLでPythonを起動して以下のようにmod1をインポートして実行すると以下のようになります.
>>> import mod1
>>> print(mod1.hello())
Hello!

また,以下のコードを作成して,ex.pyという名前で(mod1.pyと同じディレクトリに)保存します.
import mod1

print(mod1.hello())

そして,以下のようにターミナルからex.pyを実行すると以下のように表示されます.
$ python3 ex.py
Hello!
ex.pyでは,モジュール mod1 をインポートしています.この命令によって,同じディレクトリにあるmod1.pyが読み込まれます.この例のように,モジュールをインポートした際には同じディレクトリ内のファイルが優先的に探索されます(先述の datetime のような標準モジュールは,Pythonのシステム内に組み込まれており,システム内の特定のディレクトリから探索されてインポートされます).
なお,モジュールをインポートする時に,グローバル領域にある文は実行される(下のex2.pyの例で確認できます)ことに注意が必要です.

以下のコードをmod2.pyという名前で保存します.
def meow():
    print("Meow!")

print("I am imported"# "print" is in the global area

mod2.pyと同じディレクトリにex2.pyという名前で以下のコードを保存します.
import mod2

print("Bowwow!")

mod2.meow()

ここで,ex2.pyを実行すると,mod2.pyのグローバル領域にあるprint関数がインポートした際(最初)に実行されていることがわかります.
$ python3 ex2.py
I am imported
Bowwow!
Meow!

インポート時に何らかの副作用が起こるのは,多くの場合は望まれる動作でないことがほとんどなので,注意が必要です.

同一のファイルをモジュールと実行スクリプトの両方で利用して,インポート時には(上記のような)副作用が生じないようにするときの例を示します.
以下のコードをmod3.pyという名前で保存します.
def meow():
    print("Meow!")

def main():
    print("Entering main")
    meow()


if __name__ == "__main__"

    main()

以下のコードをex3.pyという名前で保存します.
import mod3


mod3.meow()

ex3.pyとmod3.pyを順番に実行してみます.
$ python3 ex3.py
Meow!

$ python3 mod3.py
Entering main
Meow!
mod3.py のif文は,もしこのファイルが直接実行された(モジュールとしてインポートされていない)場合を表すif文です.なので,直接実行された時だけmain関数が呼ばれることになります.

上記の例では,ex3.pyが実行された場合はmod3のモジュールがインポートされているので,meow関数のみが呼ばれて実行されています.mod3.pyを実行した場合には,main関数が呼ばれて実行されていることが確認できます.

上記のコードや内容は機械学習のエッセンスを参考にしています.

2017年12月26日火曜日

[Python] オブジェクト指向

標準ライブラリの利用
Pythonをインストールした際に,最初から入っているライブラリは標準ライブラリと呼ばれます.標準ライブラリ内では,関連する機能の塊は,モジュールという単位で提供されます.

以下に,標準ライブラリのクラスとして,datetimeモジュールに含まれるdataの例を示します.
>>> import datetime
>>> d = datetime.date(2017, 12, 26)
>>> d.year
2017
>>> d.weekday()
1
>>> 
dateクラスは日付を表現するためのクラスで,上記の例では
datetime.date 
(モジュール名).(クラス名)
の形式で呼び出しています.ここでは,2017年12月26日に相当するインスタンスを生成しています.

インスタンスへのアクセスは全て属性を通して行われます.属性は上記の例では
d.year
(インスタンスを表す変数).(属性名)
のように,インスタンスを表す変数にピリオド( . )と属性名で指定されます.d.year はインスタンス d 内の year 属性を参照するという命令です.例における year のような属性はデータ属性,またはプロパティと呼ばれます.
d.weekend() はインスタンス d 内のweekend 属性を呼び出しています.このような属性はメソッドと呼ばれています.メソッドは"()"とともに,場合によっては引数付きで呼ばれます.一方,データ属性は属性名のみでアクセスできます.

クラス定義
上記では標準ライブラリ(すなわち既存のクラス)について説明しました.既存のものではなく自分でクラスを作成することも可能です.

まずはデータ属性しか持たないクラスの例(ここでは Person という名前にしています)を示します.
>>> class Person: 
...     def __init__(self, first_name = "", last_name = ""): 
...             self.first_name = first_name
...             self.last_name = last_name
... 
>>> 
>>> person1 = Person("John", "Smith")
>>> print(person1.first_name, person1.last_name)
John Smith
>>> 
>>> person2 = Person()
>>> person2.first_name = "Robert"
>>> person2.last_name = "Johnson"
>>> print(person2. first_name, person2.last_name)
Robert Johnson
__init__はコンストラクタと呼ばれ,クラスのインスタンス化の際に呼ばれます.__init__の最初の引数はselfで,これは自分自身を表す変数です.self はメソッドを定義する際には必ず必要になります.
上記の例では
__init__(self, first_name = "", last_name = ""): 

のように引数が3つあります.最初は先述の self です.後の2つが実質的に外から与えることのできる引数で,上記の例では2つの引数  first_name, last_name にデフォルト値が設定されています.first_name,last_nameなどはクラスのインスタンスに付随するデータ属性です.

クラスを定義した後の
person1 = Person("John", "Smith")

では,Personクラスをインスタンス化して変数person1に代入しています.(2番目以降の引数には"John"と"Smith"が与えられており,インスタンス内のデータ属性には"John"と"Smith"が設定されていることになります.なので,その次の行の
print(person1.first_name, person1.last_name)

という命令の結果,引数(クラスのインスタンスに付属するデータ属性である John とSmith)が表示されています.

その次の
person2 = Person()

ではデフォルト値を利用してインスタンスを作成しています.インスタンスを上記の命令で作成した後に,
person2.first_name = "Robert"
person2.last_name = "Johnson"

データ属性に直接代入することでデータ属性の値を置き換えています.

続いて,上記のコード(Personクラス)にメソッドを追加してみます.追加するメソッドはget_nameという名前をつけたものと,__str__メソッドです.
>>> class Person:
...     def __init__(self, first_name = "", last_name = ""):
...             self.first_name = first_name
...             self.last_name = last_name

...     def get_name(self):
...             return self.first_name + " " +self.last_name

...     def __str__(self):
...             return self.last_name + ", " + self.first_name
ここで get_name というメソッドは,first_name と last_name をスペースで繋いだ文字列を返します.get_name を呼び出すときは,インスタンス person1 に対して,person1.get_name() のように明示的にメソッドを呼び出しています.
>>> print(person1.get_name())
John Smith

また,print(person1)とすると,person1の__str__メソッドが呼び出されます.このように明示的に指定しなくても呼び出されるメソッドのことを特殊メソッドと呼びます.
特殊メソッドはアンダースコア2つ( __ )で始まり,アンダースコア2つで終わるメソッド名を持ち,どのような時にどの特殊メソッドが呼ばれるかは決まっています.
__str__ という特殊メソッドは,print の引数に与えられたときなどの,文字列型への暗黙的変換が行われるときに呼び出されるメソッドです.
>>> print(person1)
Smith, John

上記のコードや内容は機械学習のエッセンスを参考にしています.

2017年12月25日月曜日

[Python] 関数のヘルプ

関数の使い方を忘れた際には help 関数を用いることができます.
以下は,前回の投稿で用いた query 関数の使い方を調べてみた結果です.
>>> help(sample_df.query)

Help on method query in module pandas.core.frame:

query(expr, inplace=False, **kwargs) method of pandas.core.frame.DataFrame instance
    Query the columns of a DataFrame with a boolean expression.
    
    Parameters
    ----------
    expr : string
        The query string to evaluate.  You can refer to variables
        in the environment by prefixing them with an '@' character like
        ``@a + b``.
    inplace : bool
        Whether the query should modify the data in place or return
        a modified copy
    
        .. versionadded:: 0.18.0
    
    kwargs : dict
        See the documentation for :func:`pandas.eval` for complete details
        on the keyword arguments accepted by :meth:`DataFrame.query`.
    
    Returns
    -------
    q : DataFrame
    
    See Also
    --------
    pandas.eval
    DataFrame.eval
    
    Notes
    -----
    The result of the evaluation of this expression is first passed to
    :attr:`DataFrame.loc` and if that fails because of a
    multidimensional key (e.g., a DataFrame) then the result will be passed
    to :meth:`DataFrame.__getitem__`.
    
    This method uses the top-level :func:`pandas.eval` function to
    evaluate the passed query.
    
    The :meth:`~pandas.DataFrame.query` method uses a slightly
    modified Python syntax by default. For example, the ``&`` and ``|``
    (bitwise) operators have the precedence of their boolean cousins,
    :keyword:`and` and :keyword:`or`. This *is* syntactically valid Python,
    however the semantics are different.
    
    You can change the semantics of the expression by passing the keyword
    argument ``parser='python'``. This enforces the same semantics as
    evaluation in Python space. Likewise, you can pass ``engine='python'``
    to evaluate an expression using Python itself as a backend. This is not
    recommended as it is inefficient compared to using ``numexpr`` as the
    engine.
    
    The :attr:`DataFrame.index` and
    :attr:`DataFrame.columns` attributes of the
    :class:`~pandas.DataFrame` instance are placed in the query namespace
    by default, which allows you to treat both the index and columns of the
    frame as a column in the frame.
    The identifier ``index`` is used for the frame index; you can also
    use the name of the index to identify it in a query. Please note that
    Python keywords may not be used as identifiers.
    
    For further details and examples see the ``query`` documentation in
    :ref:`indexing <indexing.query>`.
    
    Examples
    --------
    >>> df = pd.DataFrame(np.random.randn(10, 2), columns=list('ab'))
    >>> df.query('a > b')
    >>> df[df.a > df.b]  # same result as the previous expression
~

(END)

2017年12月24日日曜日

[Python] Numpy と Pandas の基本

NumpyやPandasはデータを読み込んだ利,整形したり,集計したりするのに便利なパッケージです.これらの外部パッケージを読み込むと,便利な関数やクラスを流用することができます.
Numpyはアレイ(正確にはndarray)というデータを保持するクラスを主に使います.また,行列演算にも強いパッケージです.
Pandasはデータフレーム(DataFrame)というデータ管理のためのとても強力なクラスを持っています.

まずはパッケージの読み込みを行います.
>>> import numpy as np
>>> import pandas as pd
これで,NumpyとPandasの二つのパッケージを読み込むことができました.また,Numpyの機能を使う場合は np.クラス名,pd.クラス名と記述します.

複数のデータをまとめたものをリスト(list)と呼びます.リストはNumpyもPandasも必要ない,Python標準のデータの形式です.リストは半角の角括弧で複数のデータを囲むことによって作ります.
>>> sample_list = [1, 2, 3, 4, 5]
>>> sample_list
[1, 2, 3, 4, 5]
リストの中身を表示するには,上記の2行目のように変数名だけを記述します.なお,以下のようにprint関数を使っても結果は同じです.

>>> print(sample_list)

[1, 2, 3, 4, 5]


リストを用いてアレイを作ります.Numpyの中で作成されたクラスを用いるので,np.array と記述します.
>>> sample_array = np.array([1, 2, 3, 4, 5])
>>> sample_array
array([1, 2, 3, 4, 5])

アレイに対する演算は,アレイの中身のデータ全てに対して一律に適用される.例えば足し算ならば以下のようになる.
>>> sample_array + 2
array([3, 4, 5, 6, 7])

掛け算も同様です.
>>> sample_array * 2
array([ 2,  4,  6,  8, 10])

同一のアレイには,同一のデータの型しか入れることができません.仮に,数値型と文字列型を同時に入れようとすると,全てが文字列型として扱われてしまいます.
>>> np.array([1, 2, "A"])
array(['1', '2', 'A'], dtype='<U21')

2次元の配列を作ることもできます.2次元配列を作るときには,リストを入れ子にしたものを引数に指定します.
>>> sample_array_2 = np.array(
...     [[1, 2, 3, 4, 5],
...      [6, 7, 8, 9, 10]])
>>> sample_array_2
array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10]])

行数や列数は以下のようにして取得できます.
>>> sample_array_2.shape
(2, 5)
2行5列と返ってきています.

アレイを作成するには,上記のように引数を直接指定する方法以外にも様々なものがあります.まずは,等差数列の例を示します.

まずは,{1, 2, 3, 4, 5}というスタートが1で差分が1の等差数列を使います.等差数列を作るには np.arange 関数を用います.引数には開始位置(start),終了位置(stop),差分(step)を指定します.終了位置は,この位置に来たら終了するという意味になるので,stopの位置はアレイの要素には含まれません.
>>> np.arange(start = 1, stop = 6, step = 1)
array([1, 2, 3, 4, 5])

続いて,0.1から始まり0.8で終わる,差分0.2の等差数列を作成します.

>>> np.arange(start = 0.1, stop = 0.8, step = 0.2)

array([0.1, 0.3, 0.5, 0.7])


なお,start =, stop =, step =という記述は省略することができます.
>>> np.arange(0.1, 0.8, 0.2)
array([0.1, 0.3, 0.5, 0.7])

同じ値を沢山格納したアレイを作る場合には np.tile 関数を使います.例えば,Aというアルファベットを5つ格納した配列を作成するには以下のようにします.
>>> np.tile("A", 5)
array(['A', 'A', 'A', 'A', 'A'], dtype='<U1')

数値を格納することも可能です.
>>> np.tile(0, 4)
array([0, 0, 0, 0])

全ての値が零であるアレイは np.zeros 関数を使うとより簡単に作成できます.引数にはアレイの要素数を指定します.
>>> np.zeros(5)
array([0., 0., 0., 0., 0.])

2次元のアレイにするときには,要素数を [行数, 列数] の潤に指定します.

>>> np.zeros([2, 3])

array([[0., 0., 0.],

       [0., 0., 0.]])

1で埋めることも可能です.

>>> np.ones([3, 3])

array([[1., 1., 1.],

       [1., 1., 1.],
       [1., 1., 1.]])

Numpyのアレイやリストはスライシングという技法を使って簡単にデータの抽出をすることができます.以下に例を示します.

まずは,1行のアレイを作ります.
>>> d1_array = np.array([1, 2, 3, 4, 5])
>>> d1_array
array([1, 2, 3, 4, 5])

データの抽出を行うには,角括弧を用います.例えば,最初の要素を取得する場合には d1_array[0] とします.Pythonではインデックスが0から始まることに注意が必要です.
>>> d1_array[0]
1
上記の例では,0番目の要素を抽出しています.

範囲を指定して抽出する場合にはコロン(:)を使います.例えば[1; 3]と指定すると,インデックスが1番と2版のものが取得されます.3の一つ前までの抽出になることに注意が必要です.
>>> d1_array[1:3]
array([2, 3])

2行以上のアレイにおいても角括弧を使うことで簡単にデータを抽出できます.以下の例では2次元のアレイを作って要素を抽出しています.
>>> d2_array = np.array(
...     [[1, 2, 3, 4, 5],
...     [6, 7, 8, 9, 10]])
>>> d2_array
array([[ 1,  2,  3,  4,  5],
       [ 6,  7,  8,  9, 10]])
行インデックス,列インデックスの順番に番号を指定することで要素を抽出します.
インデックスは0始まりなので,[0, 3]は1行目4列目となることに注意が必要です.
>>> d2_array[0, 3]
4
コロン記号を使うことで複数の要素を抽出できます.

続いて,Pandasのデータフレームを使用してみます.
データフレームでは,列の名称と列に格納するデータを 'col1': sample_array のようにして指定します.
アレイと異なり,データフレームは列が異なれば数値型と文字列型を混在させることが可能です.
>>> sample_df = pd.DataFrame({
...     'col1' : sample_array,
...     'col2' : sample_array * 2, 
...     'col3' : ["A", "B", "C", "D", "E"]
... })
>>> print(sample_df)
   col1  col2 col3
0     1     2    A
1     2     4    B
2     3     6    C
3     4     8    D
4     5    10    E

上記の例ではデータフレームを表示させるために print関数を用いていますが,sample_df としても同じ結果が得られます(ただし,Jupyter Notebookでは見た目が変わります).
>>> sample_df
   col1  col2 col3
0     1     2    A
1     2     4    B
2     3     6    C
3     4     8    D
4     5    10    E

データフレームは,上記のように自分で作成する場合もありますが,既存の外部データを読み込む際にも用いられます.
例えば,データが .csv ファイルで保存されていて,作業中のディレクトリと同じ場所に格納されているときには,以下のようにしてデータを読み込みます.
データを格納する変数名 = pd.read_csv("ファイル名")
今回は,2-4-1-sample_data.csv *というファイルを読み込んでみます.読み込まれたデータはデータフレームとなっています.
>>> file_data = pd.read_csv("2-4-1-sample_data.csv")
>>> print(file_data)
   col1 col2
0     1    A
1     2    A
2     3    B
3     4    B
4     5    C
5     6    C

作成されたデータフレームを結合して,新たなデータフレームを作ることも可能です.
まずは,データフレームを2つ作ります.
>>> df_1 = pd.DataFrame({
...     'col1' : np.array([1, 2, 3]),
...     'col2' : np.array(["A", "B", "C"])
... })
>>> df_2 = pd.DataFrame({
...     'col1' : np.array([4, 5, 6]), 
...     'col2' : np.array(["D", "E", "F"])
... })
>>> df_1
   col1 col2
0     1    A
1     2    B
2     3    C
>>> df_2
   col1 col2
0     4    D
1     5    E
2     6    F

これらのデータフレームを縦方向に繋げるには,pd.concat関数を用います.
>>> print(pd.concat([df_1, df_2]))
   col1 col2
0     1    A
1     2    B
2     3    C
0     4    D
1     5    E
2     6    F
3行2列のデータフレームを縦方向に二つ繋げるので,結果は6行2列のデータフレームになります.

>>> pd.concat([df_1, df_2]).shape

(6, 2)


続いて,横方向に結合させます.横方向に結合するには,axis = 1 という引数を追加します.
>>> print(pd.concat([df_1, df_2], axis = 1))
   col1 col2  col1 col2
0     1    A     4    D
1     2    B     5    E
2     3    C     6    F
3行2列のデータフレームを横方向に二つ繋げるので,結果は3行4列のデータフレームになります.

>>> pd.concat([df_1, df_2], axis = 1).shape

(3, 4)


pd.concat 関数は他にも様々な結合をさせることが可能です.データベースの操作に使うSQLがわかれば,より複雑な挙動をさせることも可能です.

データフレームには,データの抽出などの操作を行う関数が豊富にあります.以下にいくつか例を示します.
例には,以前に作成した sample_df(5行3列のデータ)を用います.
>>> sample_df
   col1  col2 col3
0     1     2    A
1     2     4    B
2     3     6    C
3     4     8    D
4     5    10    E

列名を指定して取得する場合はドット記号(.)を用います.
>>> print(sample_df.col2)
0     2
1     4
2     6
3     8
4    10
Name: col2, dtype: int64

以下のように角括弧を使う方法もあります.
>>> print(sample_df["col2"])
0     2
1     4
2     6
3     8
4    10
Name: col2, dtype: int64

複数列を抽出することも可能です.複数列を抽出するには,列名を指定する角括弧の中にリスト形式で列名を複数指定します.
>>> print(sample_df[["col2", "col3"]])
   col2 col3
0     2    A
1     4    B
2     6    C
3     8    D
4    10    E

抽出ではなく,削除することも可能です.
>>> print(sample_df.drop("col1", axis = 1))
   col2 col3
0     2    A
1     4    B
2     6    C
3     8    D
4    10    E
削除するときには,.drop 関数を用いて,丸括弧になることに注意が必要です.

sample_df の最初の指定行を取得するには,head 関数を用います.
>>> print(sample_df.head(n = 3))
   col1  col2 col3
0     1     2    A
1     2     4    B
2     3     6    C
上記の例のように .head( n = 3)というように,取得する行を指定します.指定した数字(例では3)の前の行までが取得されます.

さらに,query 関数を使って特定の行のみを取得することも可能です.
>>> print(sample_df.query('index == 0'))
   col1  col2 col3
0     1     2    A
上記の例では,index == 0 ということで1行目の身を取得しています.

query関数を用いると,様々な条件でデータを取得することが可能です.
以下は,col3 という列の値がAである行のみを抽出するには以下のようにします.
>>> print(sample_df.query('col3 == "A"'))
   col1  col2 col3
0     1     2    A

複数の条件を指定することも可能です.
query('col3 == "A" | col3 == "D"') と指定すると,col3 がAまたはD であるという条件で抽出できる.または( | )の条件はOR条件とも呼ばれます.
>>> print(sample_df.query('col3 == "A" | col3 == "D"'))
   col1  col2 col3
0     1     2    A
3     4     8    D

query('col3 == "A" & col3 == "3"') と指定すると,col3がAであり,かつ,col1が3であるという条件で抽出することになります.かつ(&)の条件はAND条件とも呼ばれます.
>>> print(sample_df.query('col3 == "A" & col1 == "3"'))
Empty DataFrame
Columns: [col1, col2, col3]
Index: []
今回の例では,sample_df の中に条件を満たす行がないので,上記のように返ってきます.

行と列を指定することもできます.
>>> print(sample_df.query('col3 == "A"') [["col2", "col3"]])
   col2 col3
0     2    A

pandasデータフレームにおいて1列だけを抽出したものは,シリーズと呼ばれる別のデータの型に変わります.
まずは,sample_df のクラス名がDataFrameになっていることを確認します.
>>> type(sample_df)
<class 'pandas.core.frame.DataFrame'>

続いて,1列だけ抽出した結果のクラス名を調べます.
>>> type(sample_df.col1)
<class 'pandas.core.series.Series'>
DataFrameではなく,Seriesと表示されていることがわかります.
シリーズは,Numpyアレイとほぼ同様に扱うことが可能です(シリーズを自分で作成することは少ないのですが,1列だけを抽出すると,自動的にシリーズ形式になるので,分析を行う際にしばしば登場します).

シリーズはアレイとぼぼ同様に扱えるものの,アレイの方が扱いやすい場合もあります.シリーズをアレイに変換する場合には,np.array の引数にシリーズ型の変数を入れます.
>>> type(np.array(sample_df.col1))
<class 'numpy.ndarray'>

シリーズに対して,.value と付けてもアレイとして抽出することが可能です.
>>> type(sample_df.values)
<class 'numpy.ndarray'>

この投稿をJupyter Notebookで実行した結果はGiHubで見ることができます.

2-4-1-sample_data.csvの中身
col1,col2
1, A
2, A
3, B
4, B
5, C
6, C