按日期迭代熊猫数据框的正确方法
Posted
技术标签:
【中文标题】按日期迭代熊猫数据框的正确方法【英文标题】:Correct way of iterating over pandas dataframe by date 【发布时间】:2014-06-16 05:25:24 【问题描述】:我想按日期迭代数据框的主轴日期。
示例:
tdf = df.ix[date]
我遇到的问题是 df.ix
返回的类型发生了变化,给我留下了 3 种可能的情况
如果tdf
中不存在日期,则会引发错误:KeyError: 1394755200000000000
如果tdf
中只有一项:print type(tdf)
返回
<class 'pandas.core.series.Series'>
如果tdf
中有多个项目:print type(tdf)
返回
<class 'pandas.core.frame.DataFrame'>
为了避免第一种情况,我可以简单地将其包装在 try catch
块中,或者感谢 jxstanford,我可以使用 if date in df.index:
避免 try catch 块
后来我遇到了这个问题,API 与 pandas 系列和 pandas 数据框不一致。我可以通过检查类型来解决这个问题,但似乎我不应该这样做。理想情况下,我希望保持类型相同。有更好的方法吗?
我正在运行 pandas 0.13.1,我目前正在使用 CSV 从 CSV 加载数据
这是一个演示问题的完整示例。
from pandas import DataFrame
import datetime
path_to_csv = '/home/n/Documents/port/test.csv'
df = DataFrame.from_csv(path_to_csv, index_col=3, header=0, parse_dates=True, sep=',')
start_dt = df.index.min()
end_dt = df.index.max()
dt_step = datetime.timedelta(days=1)
df.sort_index(inplace=True)
cur_dt = start_dt
while cur_dt != end_dt:
if cur_dt in df.index:
print type(df.ix[cur_dt])
#run some other steps using cur_dt
cur_dt += dt_step
演示该问题的示例 CSV 如下:
value1,value2,value3,Date,type
1,2,4,03/13/14,a
2,3,3,03/21/14,b
3,4,2,03/21/14,a
4,5,1,03/27/14,b
上面的代码打印出来
<class 'pandas.core.series.Series'>
<class 'pandas.core.frame.DataFrame'>
是否可以以一致的方式从 tdf 获取 value1
的值?还是我坚持为每个案例做一个 if 语句并分别处理?
if type(df.ix[cur_dt]) == DataFrame:
....
if type(df.ix[cur_dt]) == Series:
....
【问题讨论】:
您可以使用unique
获得所有日期的唯一列表,然后遍历该列表。
@KarlD。我需要其他所有日期,而不仅仅是数据框中缺少许多日期的唯一值。
尝试使用 DataFrame.from_csv 而不是 pandas.read_csv。这可能有助于解决您的问题 2 和 3。
你真的必须提供更多的细节,一个初学者的玩具数据集。你得到的行为是预期的:如果你提取一行,你得到一个系列(一维数组),如果你提取多行,它是一个 DataFrame(二维数组)。如果你告诉 pandas 寻找不存在的东西,它会给你一个错误。如果你解释你想要的结果是什么(一列?更多列?),那么有一些方法可以处理所有这些问题。
@jxstanford 谢谢我试过你的建议我仍然遇到同样的问题,
【参考方案1】:
不确定您要对数据框做什么,但这可能比尝试/例外更好:
tdf = DataFrame.from_csv(path_to_csv, index_col=3, header=0, parse_dates=True, sep=',')
while cur_dt != end_dt:
if cur_dt in df.index:
# do your thing
cur_dt += dt_step
【讨论】:
这确实有帮助!但我遇到其他问题我会更新问题【参考方案2】:您可以使用DataFrame的apply
方法,使用axis = 1
处理DataFrame的每一行来构建一个Series 具有相同的索引。
例如
def calculate_value(row):
if row.date == pd.datetime(2014,3,21):
return 0
elif row.type == 'a':
return row.value1 + row.value2 + row.value3
else:
return row.value1 * row.value2 * row.value3
df['date'] = df.index
df['NewValue'] = df.apply(calculate_value, axis=1)
如下修改您的示例输入
value1 value2 value3 type NewValue date
Date
2014-03-13 1 2 4 a 7 2014-03-13
2014-03-21 2 3 3 b 0 2014-03-21
2014-03-21 3 4 2 a 0 2014-03-21
2014-03-27 4 5 1 b 20 2014-03-27
[4 rows x 6 columns]
【讨论】:
【参考方案3】:这个玩具代码将一致地返回 DataFrames。
def framer(rows):
if ndim(rows) == 1:
return rows.to_frame().T
else:
return rows
for cur_date in df.index:
print type(framer(df.ix[cur_date]))
这会给你缺少的日子:
df.resample(rule='D')
查看重采样方法文档字符串。它有自己的选项来填补缺失的数据。如果您决定将多个日期合并为一个日期,您正在查看的方法是 groupby(如果您想跨行组合值)和 drop_duplicates(如果你想忽略它们)。无需重新发明***。
【讨论】:
以上是关于按日期迭代熊猫数据框的正确方法的主要内容,如果未能解决你的问题,请参考以下文章