使用方括号访问Pandas列与使用点(类似属性)访问Pandas列

byqmnocz  于 2023-01-24  发布在  其他
关注(0)|答案(5)|浏览(208)

在以下两种情况下:

import pandas

d = {'col1': 2, 'col2': 2.5}
df = pandas.DataFrame(data=d, index=[0])

print(df['col2'])
print(df.col2)

这两种方法都可以用于对列进行索引并产生相同的结果,那么它们之间有什么区别吗?

pjngdqdw

pjngdqdw1#

“点标记”,即df.col2是为了方便而公开的属性访问。
您可以将Series上的索引、DataFrame上的列以及Panel上的项目直接作为属性进行访问:
df['col2']执行相同的操作:它返回列的pd.Series
关于属性访问的一些警告:

  • 您不能添加列(df.new_col = x不起作用,更糟的是:它将静默地实际创建一个新属性,而不是一个列-在这里考虑monkey-patching)
  • 如果列名中有空格或者列名是整数,则该函数将不起作用。
bbuxkriu

bbuxkriu2#

只要您访问的是名称简单的单列,它们就相同,但是您可以使用括号表示法执行更多操作。仅当列名是有效的Python标识符时,才可以使用df.col(例如,不包含空格和其它这样的东西)。而且,如果列名与panda方法名冲突,可能会遇到意外情况使用方括号可以选择多个列(例如df[['col1', 'col2']])或添加新列(df['newcol'] = ...),而点访问无法实现这一点。
你链接到的另一个问题也适用,但这是一个更一般的问题。Python对象可以定义.[]操作符如何应用于它们。Pandas DataFrames已经选择让它们在访问单列的有限情况下保持相同,并给出了上述警告。

0sgqnhkj

0sgqnhkj3#

差异的简短回答:

      • []索引**(方括号访问)具有操作DataFrame列数据的完整功能。
  • 属性访问(点号访问)主要是为了方便访问现有DataFrame列数据,但偶尔也有其局限性(如特殊列名、创建新列)。

更多说明

Series和DataFrame是panda的核心类和数据结构,当然它们也是Python类,所以在涉及panda DataFrame和普通Python对象之间的属性访问时,会有一些细微的区别。但是,这些都有很好的文档记录,很容易理解。这里有几点需要注意:
1.在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.'}

1.在Pandas中,* index * 和 * column * 与数据结构密切相关,您可以访问Series上的索引、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': {}}

1.但是,Pandas属性访问主要是为了方便读取和修改数据框的Series或列的现有元素

>>> df.a
0    7
1    5
Name: a, dtype: int64
>>> df.b = [1, 1]
>>> df
   a  b
0  7  1
1  5  1

1.而且,方便性是完整功能的一个折衷,例如,你可以创建一个列名称为['space bar', '1', 'loc', 'min', 'index']的DataFrame对象,但是你不能将它们作为属性来访问,因为它们不是有效的Python标识符(1space 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

1.在这些情况下,.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(不再是silent)。*

>>> 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}

1.最后,要为DataFrame创建新列,切勿使用属性访问。正确的方法是使用[].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
raogr8fs

raogr8fs4#

.表示法在交互式工作和探索时非常有用。但是,为了代码清晰和避免发生疯狂的事情,您绝对应该使用[]表示法。下面是创建新列时为什么应该使用[]的示例。

df = pd.DataFrame(data={'A':[1, 2, 3],
                    'B':[4,5,6]})

# this has no effect
df.D = 11
df

    A  B
 0  1  4
 1  2  5
 2  3  6
# but this works
df['D'] = 11
df

Out[19]: 
   A  B   D
0  1  4  11
1  2  5  11  
2  3  6  11
x8goxv8g

x8goxv8g5#

如果您有这样的 Dataframe (我推荐这些列名)...

df = pd.DataFrame({'min':[1,2], 'max': ['a','a'], 'class': [1975, 1981], 'sum': [3,4]})

print(df)

   min max  class  sum
0    1   a   1975    3
1    2   a   1981    4

看起来一切正常,没有错误。您甚至可以通过df['min']等访问列...

print(df['min'])

0    1
1    2
Name: min, dtype: int64

但是,如果您尝试使用df.<column_name>,则会遇到问题:

print(df.min)

<bound method NDFrame._add_numeric_operations.<locals>.min of    min max  class  sum
0    1   a   1975    3
1    2   a   1981    4>

print(df.max)

<bound method NDFrame._add_numeric_operations.<locals>.max of    min max  class  sum
0    1   a   1975    3
1    2   a   1981    4>

print(df.class)

  File "<ipython-input-31-3472b02a328e>", line 1
    print(df.class)
             ^
SyntaxError: invalid syntax
    
print(df.sum)

<bound method NDFrame._add_numeric_operations.<locals>.sum of    min max  class  sum
0    1   a   1975    3
1    2   a   1981    4>

相关问题