如何使用字段名称变量访问 namedtuple 的字段?

新手上路,请多包涵

我可以按名称访问命名元组的元素,如下所示 (*):

 from collections import namedtuple
Car = namedtuple('Car', 'color mileage')
my_car = Car('red', 100)
print my_car.color

但是如何使用变量来指定我要访问的字段的名称呢?例如

field = 'color'
my_car[field] # doesn't work
my_car.field # doesn't work

我的实际用例是我正在使用 for row in data.itertuples() 遍历熊猫数据框。我正在对特定列的值执行操作,并且我希望能够指定要按名称使用的列作为包含此循环的方法的参数。

(*) 示例取自此处。我正在使用 Python 2.7。

原文由 LangeHaare 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 437
2 个回答

你可以使用 getattr

 getattr(my_car, field)

原文由 juanpa.arrivillaga 发布,翻译遵循 CC BY-SA 3.0 许可协议

‘getattr’ 答案有效,但还有另一种选择稍快一些。

 idx = {name: i for i, name in enumerate(list(df), start=1)}
for row in df.itertuples(name=None):
   example_value = row[idx['product_price']]

解释

制作一个将列名映射到行位置的字典。使用“name=None”调用“itertuples”。然后使用使用字典中的列名获得的索引访问每个元组中的所需值。

  1. 制作字典以查找索引。

idx = {name: i for i, name in enumerate(list(df), start=1)}

  1. 使用字典在行元组中按名称访问所需的值
for row in df.itertuples(name=None):
   example_value = row[idx['product_price']]

注意:使用 start=0enumerate 如果你调用 itertuples index=False

这是一个工作示例,显示了两种方法和两种方法的时间。

 import numpy as np
import pandas as pd
import timeit

data_length = 3 * 10**5
fake_data = {
    "id_code": list(range(data_length)),
    "letter_code": np.random.choice(list('abcdefgz'), size=data_length),
    "pine_cones": np.random.randint(low=1, high=100, size=data_length),
    "area": np.random.randint(low=1, high=100, size=data_length),
    "temperature": np.random.randint(low=1, high=100, size=data_length),
    "elevation": np.random.randint(low=1, high=100, size=data_length),
}
df = pd.DataFrame(fake_data)

def iter_with_idx():
    result_data = []

    idx = {name: i for i, name in enumerate(list(df), start=1)}

    for row in df.itertuples(name=None):

        row_calc = row[idx['pine_cones']] / row[idx['area']]
        result_data.append(row_calc)

    return result_data


def iter_with_getaatr():

    result_data = []
    for row in df.itertuples():
        row_calc = getattr(row, 'pine_cones') / getattr(row, 'area')
        result_data.append(row_calc)

    return result_data


dict_idx_method = timeit.timeit(iter_with_idx, number=100)
get_attr_method = timeit.timeit(iter_with_getaatr, number=100)

print(f'Dictionary index Method {dict_idx_method:0.4f} seconds')
print(f'Get attribute method {get_attr_method:0.4f} seconds')

结果:

 Dictionary index Method 49.1814 seconds
Get attribute method 80.1912 seconds

我假设差异是由于创建元组与命名元组的开销较低,并且通过索引而不是 getattr 访问它的开销也较低,但这两者都只是猜测。如果有人知道更好,请发表评论。

我没有探讨列数与行数如何影响计时结果。

原文由 Mint 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题