使用方括号访问 Pandas 列与使用点(类似属性)
- 2024-12-20 08:38:00
- admin 原创
- 79
问题描述:
在以下两种情况下:
import pandas
d = {'col1': 2, 'col2': 2.5}
df = pandas.DataFrame(data=d, index=[0])
print(df['col2'])
print(df.col2)
两种方法都可以用于对列进行索引并产生相同的结果,那么它们之间有什么区别吗?
解决方案 1:
“点符号”,即df.col2
为了方便而公开的属性访问。
您可以直接将 Series 上的索引、DataFrame 上的列以及 Panel 上的项目作为属性进行访问:
df['col2']
作用相同:它返回pd.Series
该列的。
关于属性访问的一些注意事项:
您无法添加列(
df.new_col = x
不起作用,更糟糕的是:它实际上会默默地创建一个新属性而不是一个列 - 想想这里的 monkey-patching)如果列名中有空格或者列名是整数,则它将不起作用。
解决方案 2:
差异的简短答案:
[]
索引(方括号访问)具有对 DataFrame 列数据进行操作的全部功能。虽然属性访问(点访问)主要是为了方便访问现有的 DataFrame 列数据,但偶尔也有其局限性(例如特殊列名、创建新列)。
更多解释
Series 和 DataFrame 是 Pandas 中的核心类和数据结构,当然它们也是 Python 类,因此在涉及 Pandas DataFrame 和普通 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.'}
在 pandas 中,索引和列与数据结构紧密相关,你可以将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': {}}
但是,pandas 属性访问主要是为了方便读取和修改Series 或 DataFrame 的列的现有元素。
>>> df.a
0 7
1 5
Name: a, dtype: int64
>>> df.b = [1, 1]
>>> df
a b
0 7 1
1 5 1
而且,便利性是以牺牲完整功能为代价的。例如,您可以创建一个具有列名的 DataFrame 对象
['space bar', '1', 'loc', 'min', 'index']
,但不能将它们作为属性访问,因为它们不是有效的 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
另一个重要的区别是尝试为 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 创建新列,切勿使用属性访问。正确的方法是使用
[]
或.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
解决方案 3:
只要您使用简单名称访问单个列,它们就是一样的,但您可以使用括号表示法做更多的事情。只有df.col
当列名是有效的 Python 标识符(例如,不包含空格和其他类似的东西)时,您才能使用。此外,如果您的列名与 pandas 方法名称(如sum
)冲突,您可能会遇到意外情况。使用括号,您可以选择多个列(例如df[['col1', 'col2']]
)或添加一个新列(df['newcol'] = ...
),而使用点访问则无法做到这一点。
您链接到的另一个问题也适用,但这是一个更普遍的问题。Python 对象可以定义.
and[]
运算符如何应用于它们。Pandas DataFrames 选择使它们在这种访问单个列的有限情况下相同,但有上述注意事项。
解决方案 4:
.
符号在交互工作和探索时非常有用。但是,为了代码清晰并避免发生疯狂的事情,您绝对应该使用符号。以下是创建新列时应[]
使用符号的示例。[]
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
解决方案 5:
如果您有这样的数据框(我不推荐这些列名)...
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>
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理必备:盘点2024年13款好用的项目管理软件