2017-03-29 6 views
2

これは比較的簡単です。Pandas Dataframeカラムの操作はインデックスを使用

A B C 
1/8/2017 1/11/2017 1/20/2017 1/25/2017 
1/9/2017 1/11/2017 1/20/2017 1/25/2017 
1/10/2017 1/11/2017 1/20/2017 1/25/2017 
1/11/2017 1/20/2017 1/25/2017 1/31/2017 
1/12/2017 1/20/2017 1/25/2017 1/31/2017 
1/13/2017 1/20/2017 1/25/2017 1/31/2017 

私はDates.indexと日付の差を利用したいと思います。私はパンダのデータフレーム(日付)を持っています。

A B C 
1/8/2017  3 12  17 
1/9/2017  2 11  16 
1/10/2017 1 10  15 
1/11/2017 9 14  20 
1/12/2017 8 13  19 
1/13/2017 7 12  18 

当然のことながら、私はこの試みた:出力がそうするようなものだ

Dates - Dates.index 

をしかし、私はこの素敵なTypeError例外受け取る:代わりに

TypeError: Could not operate DatetimeIndex...with block values ufunc subtract cannot use operands with types dtype('<M8[ns]') and dtype('O') 

を、私はループには書かれてきました列ごとに移動しますが、それはちょうど愚かなようです。誰もこれを行うためにpythonic方法を提案することはできますか?

EDIT

In [1]: import pandas as pd 
import numpy as np 
import datetime 
dates = pd.date_range('20170108',periods=6) 
df = pd.DataFrame(np.empty([len(dates),3]),index=dates,columns=list('ABC')) 
df['A'].loc[0:3] = datetime.date(2017, 1, 11) 
df['B'].loc[0:3] = datetime.date(2017, 1, 20) 
df['C'].loc[0:3] = datetime.date(2017, 1, 25) 
df['A'].loc[3:6] = datetime.date(2017, 1, 20) 
df['B'].loc[3:6] = datetime.date(2017, 1, 25) 
df['C'].loc[3:6] = datetime.date(2017, 1, 31) 

In [2]: print(df) 
        A   B   C 
2017-01-08 2017-01-11 2017-01-20 2017-01-25 
2017-01-09 2017-01-11 2017-01-20 2017-01-25 
2017-01-10 2017-01-11 2017-01-20 2017-01-25 
2017-01-11 2017-01-20 2017-01-25 2017-01-31 
2017-01-12 2017-01-20 2017-01-25 2017-01-31 
2017-01-13 2017-01-20 2017-01-25 2017-01-31 

In [3]: df = df.sub(df.index.to_series(),axis=0) 

ValueError: operands could not be broadcast together with shapes (18,) (6,) 

答えて

0

私はまだコメントできない担当者が、私はそれをここに置く:私はこれを行うためのより明示的でエレガントな方法は、単にapplyを使用することです。

df = df.apply(pd.to_datetime, axis="columns") # just to make sure values are datetime df.apply(lambda x: x - df.index.to_series(), axis="rows)

+0

これはうまく動作します。 – trob

2

あなたが必要とする最初のすべての列to_datetimeを変換してからsub使用:あなたはdtypesdatetime64が必要

#if dtypes of all columns are datetime, omit it 
date_cols = list('ABC') 
for col in df.columns: 
    df[col] = pd.to_datetime(df[col]) 

df = df.sub(df.index.to_series(),axis=0) 
print (df) 
       A  B  C 
2017-01-08 3 days 12 days 17 days 
2017-01-09 2 days 11 days 16 days 
2017-01-10 1 days 10 days 15 days 
2017-01-11 9 days 14 days 20 days 
2017-01-12 8 days 13 days 19 days 
2017-01-13 7 days 12 days 18 days 

:(

dates = pd.date_range('20170108',periods=6) 
df = pd.DataFrame(index=dates) 
df.loc[0:3, 'A'] = pd.Timestamp(2017, 1, 11) 
df.loc[0:3, 'B'] = pd.Timestamp(2017, 1, 20) 
df.loc[0:3, 'C'] = pd.Timestamp(2017, 1, 25) 
df.loc[3:6, 'A'] = pd.Timestamp(2017, 1, 20) 
df.loc[3:6, 'B'] = pd.Timestamp(2017, 1, 25) 
df.loc[3:6, 'C'] = pd.Timestamp(2017, 1, 31) 
print (df) 
        A   B   C 
2017-01-08 2017-01-11 2017-01-20 2017-01-25 
2017-01-09 2017-01-11 2017-01-20 2017-01-25 
2017-01-10 2017-01-11 2017-01-20 2017-01-25 
2017-01-11 2017-01-20 2017-01-25 2017-01-31 
2017-01-12 2017-01-20 2017-01-25 2017-01-31 
2017-01-13 2017-01-20 2017-01-25 2017-01-31 

print (df.dtypes) 
A datetime64[ns] 
B datetime64[ns] 
C datetime64[ns] 
dtype: object 

df = df.sub(df.index.to_series(),axis=0) 
print (df) 
       A  B  C 
2017-01-08 3 days 12 days 17 days 
2017-01-09 2 days 11 days 16 days 
2017-01-10 1 days 10 days 15 days 
2017-01-11 9 days 14 days 20 days 
2017-01-12 8 days 13 days 19 days 
2017-01-13 7 days 12 days 18 days 
+0

ソリューションが便利ですが、それはまだ私が特にないようにしようとしています列でループします。別の方法はありませんか? – trob

+1

ループスルー列はdatetimeに変換するだけです。それらがすでにdatetimeであれば、その部分をスキップすることができます – piRSquared

+0

これはdatetimeに変換するためのループです。read_csvの 'parse_dates'パラメータを使用する方が良いです – jezrael