按日期迭代pandas数据帧的正确方法

时间:2014-04-30 02:48:26

标签: python pandas

我希望按日期迭代数据框主轴。

示例:

tdf = df.ix[date]

我遇到的问题是df.ix返回的类型发生了变化,给我留下了3种可能的情况

1)如果tdf中的日期不存在,则会抛出错误,

KeyError: 1394755200000000000

2)如果tdf

中只有一个项目

print type(tdf)返回 <class 'pandas.core.series.Series'>

3)如果tdf

中有多个项目

print type(tdf)返回 <class 'pandas.core.frame.DataFrame'>

为了避免第一种情况,我可以简单地将它包装在try catch块中或者感谢jxstanford,我可以使用if date in df.index:来避免try catch块

我遇到了带有pandas系列和pandas数据帧的API不一致的问题。我可以通过检查类型来解决这个问题,但似乎我不应该这样做。理想情况下,我希望保持类型相同。有没有更好的方法呢?

我正在运行pandas 0.13.1而我正在使用

从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:
    ....

3 个答案:

答案 0 :(得分:2)

不确定您尝试使用数据帧做什么,但这可能比尝试/更好:

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

答案 1 :(得分:1)

您可以使用 DataFrame apply方法,使用axis = 1处理 DataFrame 的每一行来构建系列具有相同的索引

e.g。

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]

答案 2 :(得分:1)

此玩具代码将一致返回DataFrame。

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')

查看resample方法docstring。它有自己的选项来填补缺失的数据。如果您决定将多个日期合并为一个,那么您正在查看的方法是 groupby (如果您想要跨行组合值)和 drop_duplicates (如果你想忽略它们)。没有必要重新发明轮子。