按日期迭代熊猫数据框的正确方法

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】:

您可以使用DataFrameapply方法,使用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(如果你想忽略它们)。无需重新发明***。

【讨论】:

以上是关于按日期迭代熊猫数据框的正确方法的主要内容,如果未能解决你的问题,请参考以下文章

熊猫:将汇率查询乘以另一个数据框的相同日期后,按每日金额求和和汇总

如何加快熊猫数据框迭代

迭代 Pandas 数据框的最佳方法?

如何按天拆分熊猫数据框或系列(可能使用迭代器)

如何在熊猫中迭代数据框时保留数据类型?

熊猫:Groupby,循环并添加一小时迭代与组内的条件