すなわち:
import pandas
d = {'col1': 2, 'col2': 2.5}
df = pandas.DataFrame(data=d, index=[0])
print(df['col2'])
print(df.col2)
出力は同じです。
この回答はこのケースに適用されますか?
「ドット表記」、つまりdf.col2
は 属性アクセス です。これは便宜上公開されています。
Seriesのインデックス、DataFrameの列、Panelの項目に属性として直接アクセスできます。
df['col2']
は同じことを行います。列のpd.Series
を返します。
属性アクセスに関するいくつかの警告:
df.new_col = x
は機能しません。さらに悪いことに、静かに実際に列ではなく新しい属性を作成します-考えますモンキーパッチはこちら)単純な名前で単一の列にアクセスしている限りは同じですが、ブラケット表記を使用してさらに多くのことができます。 df.col
を使用できるのは、列名が有効なPython識別子(たとえば、スペースやその他のものが含まれていない)の場合のみです。また、列名がpandasメソッド名(sum
など)と衝突します。角かっこを使用すると、複数の列(たとえば、df[['col1', 'col2']]
)を選択したり、新しい列(df['newcol'] = ...
)、これはドットアクセスでは実行できません。
あなたがリンクした他の質問も当てはまりますが、それはもっと一般的な質問です。 Pythonオブジェクトは、.
および[]
演算子をどのように適用するかを定義します。Pandas DataFramesは同じものを選択しました単一の列にアクセスするこの限られたケースでは、上記の注意事項があります。
違いの簡単な答え:
[]
indexing(角括弧アクセス)には、DataFrame列データを操作するための完全な機能があります。さらに説明すると、SeiresとDataFrameはパンダのコアクラスとデータ構造であり、もちろんPythonクラスでもあるため、pandas DataFrameとnormal Pythonオブジェクト。しかし、それは 十分に文書化されている であり、簡単に理解できます。
Pythonでは、ユーザーは属性アクセスを使用して、独自のデータ属性をインスタンスオブジェクトに動的に追加できます。
>>> class Dog(object):
... pass
>>> dog = Dog()
>>> vars(dog)
{}
>>> superdog = Dog()
>>> vars(superdog)
{}
>>> dog.legs = 'I can run.'
>>> superdog.wings = 'I can fly.'
>>> vars(dog)
{'legs': 'I can run.'}
>>> vars(superdog)
{'wings': 'I can fly.'}
パンダでは、indexおよびcolumnはデータ構造に密接に関連しているため、アクセスできますシリーズのインデックス、DataFrameの列属性として。
>>> import pandas as pd
>>> import numpy as np
>>> data = np.random.randint(low=0, high=10, size=(2,2))
>>> df = pd.DataFrame(data, columns=['a', 'b'])
>>> df
a b
0 7 6
1 5 8
>>> vars(df)
{'_is_copy': None,
'_data': BlockManager
Items: Index(['a', 'b'], dtype='object')
Axis 1: RangeIndex(start=0, stop=2, step=1)
IntBlock: slice(0, 2, 1), 2 x 2, dtype: int64,
'_item_cache': {}}
ただし、pandas属性アクセスは、主に、シリーズまたは列の既存の要素の読み取りと変更の利便性ですDataFrame。
>>> df.a
0 7
1 5
Name: a, dtype: int64
>>> df.b = [1, 1]
>>> df
a b
0 7 1
1 5 1
また、利便性は完全な機能のトレードオフです。例えば。列名['space bar', '1', 'loc', 'min', 'index']
でDataFrameオブジェクトを作成できますが、有効なPython識別子1
、space bar
または既存のメソッド名と競合するため、属性としてアクセスできません。
>>> data = np.random.randint(0, 10, size=(2, 5))
>>> df_special_col_names = pd.DataFrame(data, columns=['space bar', '1', 'loc', 'min', 'index'])
>>> df_special_col_names
space bar 1 loc min index
0 4 4 4 8 9
1 3 0 1 2 3
これらの場合、.loc
、.iloc
、および[]
のインデックス付けは 定義された方法 であり、SeriesおよびDataFrameオブジェクトのインデックスと列に完全にアクセス/操作します。
>>> df_special_col_names['space bar']
0 4
1 3
Name: space bar, dtype: int64
>>> df_special_col_names.loc[:, 'min']
0 8
1 2
Name: min, dtype: int64
>>> df_special_col_names.iloc[:, 1]
0 4
1 0
Name: 1, dtype: int64
もう1つの重要な違いは、DataFrameの新しい列を作成するためにタイリングする場合です。ご覧のとおり、df.c = df.a + df.b
はコアデータ構造と一緒に新しい属性を作成したため、バージョン0.21.0
から開始し、後で、この動作はUserWarning
(無音)を発生させます。
>>> df
a b
0 7 1
1 5 1
>>> df.c = df.a + df.b
__main__:1: UserWarning: Pandas doesn't allow columns to be created via a new attribute name - see https://pandas.pydata.org/pandas-docs/stable/indexing.html#attribute-access
>>> df['d'] = df.a + df.b
>>> df
a b d
0 7 1 8
1 5 1 6
>>> df.c
0 8
1 6
dtype: int64
>>> vars(df)
{'_is_copy': None,
'_data':
BlockManager
Items: Index(['a', 'b', 'd'], dtype='object')
Axis 1: RangeIndex(start=0, stop=2, step=1)
IntBlock: slice(0, 2, 1), 2 x 2, dtype: int64
IntBlock: slice(2, 3, 1), 1 x 2, dtype: int64,
'_item_cache': {},
'c': 0 8
1 6
dtype: int64}
最後に、DataFrameの新しい列を作成するには、属性accessを使用しないでください。正しい方法は、[]
を使用することですまたは.loc
インデックス作成:
>>> df
a b
0 7 6
1 5 8
>>> df['c'] = df.a + df.b
>>> # OR
>>> df.loc[:, 'c'] = df.a + df.b
>>> df # c is an new added column
a b c
0 7 6 13
1 5 8 13