【问题标题】:Operation on Pandas Dataframe columns using its Index使用其索引对 Pandas Dataframe 列进行操作
【发布时间】:2017-03-29 14:44:23
【问题描述】:

这应该相对容易。我有一个熊猫数据框(日期):

    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 和 Dates 之间的区别。输出是这样的:

    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方式来做到这一点吗?

编辑

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

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    您需要先转换所有列to_datetime,然后使用sub

    #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
    

    你需要dtypesdatetime64:

    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
    

    【讨论】:

    • 虽然您的解决方案很有帮助,但它仍然按列循环,这是我特别想避免的。难道就没有别的办法了吗?
    • 列的循环只是为了转换为日期时间。如果它们已经是日期时间,那么您可以跳过该部分
    • 循环仅用于转换为日期时间,最好在 read_csv 中使用parse_dates 参数
    • 对,所以我的数据已经是日期时间格式,但是这个解决方案会产生操作数错误...“操作数不能与形状一起广播”
    • 两者,真的。我使用一些模拟代码对原始问题进行了编辑。
    【解决方案2】:

    我认为更明确和优雅的方法是简单地使用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)

    【讨论】:

      猜你喜欢
      • 2017-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-04
      • 1970-01-01
      • 1970-01-01
      • 2021-06-10
      相关资源
      最近更新 更多