[英]Python - Iterate over a list of attributes
我的數據集中有一個功能,它是一個pandas時間戳對象。 它(以及許多其他)具有以下屬性:年,小時,每周,每月。
我可以使用一些強力方法基於這些屬性創建新功能:
df["year"] = df["timeStamp"].apply(lambda x : x.year)
df["hour"] = df["timeStamp"].apply(lambda x : x.hour)
。 。 。
但是,我想迭代一個列表:
nomtimes = ["year", "hour", "month", "dayofweek"]
for i in nomtimes:
df[i] = df["timeStamp"].apply(lambda x : x.i)
我得到以下AttributeError:'Timestamp'對象沒有屬性'i',我得到它並理解為什么我有這個錯誤。
如何將引用的字符串取消引用以便我可以將其作為屬性傳遞?
你只需要getattr()
:
df[i] = df["timeStamp"].apply(lambda x : getattr(x, i))
不要在這里使用.apply
,pandas有各種內置實用程序來處理datetime對象,在系列對象上使用dt
屬性:
In [11]: start = datetime(2011, 1, 1)
...: end = datetime(2012, 1, 1)
...:
In [12]: df = pd.DataFrame({'data':pd.date_range(start, end)})
In [13]: df.dtypes
Out[13]:
data datetime64[ns]
dtype: object
In [14]: df['year'] = df.data.dt.year
In [15]: df['hour'] = df.data.dt.hour
In [16]: df['month'] = df.data.dt.month
In [17]: df['dayofweek'] = df.data.dt.dayofweek
In [18]: df.head()
Out[18]:
data year hour month dayofweek
0 2011-01-01 2011 0 1 5
1 2011-01-02 2011 0 1 6
2 2011-01-03 2011 0 1 0
3 2011-01-04 2011 0 1 1
4 2011-01-05 2011 0 1 2
或者,動態地使用getattr
:
In [24]: df = pd.DataFrame({'data':pd.date_range(start, end)})
In [25]: nomtimes = ["year", "hour", "month", "dayofweek"]
...:
In [26]: df.head()
Out[26]:
data
0 2011-01-01
1 2011-01-02
2 2011-01-03
3 2011-01-04
4 2011-01-05
In [27]: for t in nomtimes:
...: df[t] = getattr(df.data.dt, t)
...:
In [28]: df.head()
Out[28]:
data year hour month dayofweek
0 2011-01-01 2011 0 1 5
1 2011-01-02 2011 0 1 6
2 2011-01-03 2011 0 1 0
3 2011-01-04 2011 0 1 1
4 2011-01-05 2011 0 1 2
如果你必須使用單行,請使用:
In [30]: df = pd.DataFrame({'data':pd.date_range(start, end)})
In [31]: df.head()
Out[31]:
data
0 2011-01-01
1 2011-01-02
2 2011-01-03
3 2011-01-04
4 2011-01-05
In [32]: df = df.assign(**{t:getattr(df.data.dt,t) for t in nomtimes})
In [33]: df.head()
Out[33]:
data dayofweek hour month year
0 2011-01-01 5 0 1 2011
1 2011-01-02 6 0 1 2011
2 2011-01-03 0 0 1 2011
3 2011-01-04 1 0 1 2011
4 2011-01-05 2 0 1 2011
operator.attrgetter
您可以在循環中提取屬性:
from operator import attrgetter
for i in nomtimes:
df[i] = df['timeStamp'].apply(attrgetter(i))
這是一個完整的例子:
df = pd.DataFrame({'timeStamp': ['2018-05-05 15:00', '2015-01-30 11:00']})
df['timeStamp'] = pd.to_datetime(df['timeStamp'])
nomtimes = ['year', 'hour', 'month', 'dayofweek']
for i in nomtimes:
df[i] = df['timeStamp'].apply(attrgetter(i))
print(df)
timeStamp year hour month dayofweek
0 2018-05-05 15:00:00 2018 15 5 5
1 2015-01-30 11:00:00 2015 11 1 4
您的代碼將無法工作,因為您嘗試傳遞字符串而不是按名稱提取屬性。 然而,這不是正在發生的事情:語法不會提供字符串,而是嘗試直接訪問i
,如第一個示例所示。
您可能會問是否有辦法一次性從datetime
對象中提取所有屬性而不是按順序提取。 attrgetter
的好處是你可以直接指定多個屬性以完全避免for
循環:
attributes = df['timeStamp'].apply(attrgetter(*nomtimes))
df[nomtimes] = pd.DataFrame(attributes.values.tolist())
但是pd.Series.apply
只是一個薄薄的循環。 通常,沒有必要。 借用@ juanpa.arrivillaga的想法,您可以通過pd.Series.dt
訪問器直接訪問屬性:
attributes = pd.concat(attrgetter(*nomtimes)(df['timeStamp'].dt), axis=1, keys=nomtimes)
df = df.join(attributes)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.