Python 为什么熊猫对乘法的日期时间索引有不同的处理方式?

Python 为什么熊猫对乘法的日期时间索引有不同的处理方式?,python,pandas,Python,Pandas,熊猫乘法不能像我期望的那样用于列数据帧: In [1]: import pandas as pd In [2]: df = pd.DataFrame({'a': [1,2,3]}) In [3]: s = pd.Series([5,6,7]) In [4]: df * s 0 1 2 a 0 NaN NaN NaN NaN 1 NaN NaN NaN NaN 2 NaN NaN NaN NaN 如中所述,正确的方法是: 但是,对于具有日期时间索引的数据帧,这是不必要

熊猫乘法不能像我期望的那样用于列数据帧:

In [1]: import pandas as pd

In [2]: df = pd.DataFrame({'a': [1,2,3]})

In [3]: s = pd.Series([5,6,7])

In [4]: df * s

    0   1   2   a
0 NaN NaN NaN NaN
1 NaN NaN NaN NaN
2 NaN NaN NaN NaN
如中所述,正确的方法是:

但是,对于具有日期时间索引的数据帧,这是不必要的:

In [6]: import numpy as np

In [7]: days = np.arange('2000-12-20', '2000-12-23', dtype='datetime64[D]')

In [8]: df = pd.DataFrame({'a': [1,2,3]}, index=days)

In [9]: s = pd.Series([5,6,7], index=days)

In [10]: df * s

             a
2000-12-20   5
2000-12-21  12
2000-12-22  21

为什么会这样?为什么第一个示例不起作用,是否可以始终使用
*
而不是
.multiply

看起来这是较旧的不推荐行为。问题在这两种情况下,最好都是明确的

In [161]: pd.__version__
Out[161]: '0.16.2'

In [160]: df * s
....: FutureWarning: TimeSeries broadcasting along DataFrame index by default is deprecated. Please use DataFrame.<op> to explicitly broadcast arithmetic operations along the index
  FutureWarning)
Out[160]: 
             a
2000-12-20   5
2000-12-21  12
2000-12-22  21
[161]中的
:pd.\u版本__
Out[161]:“0.16.2”
In[160]:df*s
..:FutureWarning:默认情况下,不推荐沿数据帧索引进行TimeSeries广播。请使用数据框。沿索引显式广播算术运算
未来警告)
Out[160]:
A.
2000-12-20   5
2000-12-21  12
2000-12-22  21

看起来这是一种过时的行为。问题在这两种情况下,最好都是明确的

In [161]: pd.__version__
Out[161]: '0.16.2'

In [160]: df * s
....: FutureWarning: TimeSeries broadcasting along DataFrame index by default is deprecated. Please use DataFrame.<op> to explicitly broadcast arithmetic operations along the index
  FutureWarning)
Out[160]: 
             a
2000-12-20   5
2000-12-21  12
2000-12-22  21
[161]中的
:pd.\u版本__
Out[161]:“0.16.2”
In[160]:df*s
..:FutureWarning:默认情况下,不推荐沿数据帧索引进行TimeSeries广播。请使用数据框。沿索引显式广播算术运算
未来警告)
Out[160]:
A.
2000-12-20   5
2000-12-21  12
2000-12-22  21

要回答您的另一个问题,您可能可以使用
*
而不是
。在绝大多数情况下(可能是所有情况下)使用乘法
,但这是否是一种改进可能是另一个问题。您可能最好将运算符看作是添加、
等的便捷快捷方式,但这并不总是最好的方法

无论如何,如果您想在此处使用
*
,您可以执行以下任一操作:

df['a'] * s                    # convert df to series

df * pd.DataFrame(s).values    # convert s to dataframe then to array

df * s.values.reshape(3,1)     # convert s to numpy array
第一个是很明显的,你只是把事情设置成两个系列,然后事情按照你想要的方式进行。请注意,这比将两者转换为数据帧更容易,因为在相乘系列时只需要对齐索引(轴=0),但在相乘数据帧时需要对齐索引和列(轴=1)。尽管您可以通过给系列指定与要乘以的数据帧列相同的名称来解决这个问题

第二种和第三种方法更有趣、更一般。它们通过转换为numpy数组来摆脱索引。这样做可以让您自由地做很多不同的事情,但请记住,这可能是危险的,因为您会显式地忽略索引,这意味着由您来确保它们正确排列


另外请注意,一般情况下,您可以使用
.values.shape
来更好地了解尝试乘法、除法等操作时的维度。通常,当这些操作失败时,快速检查形状会告诉您原因。

要回答其他问题,在绝大多数情况下(可能全部),您可能会使用
*
而不是
。乘法
,但这是否是一种改进可能是另一个问题。您可能最好将运算符看作是添加、
等的便捷快捷方式,但这并不总是最好的方法

无论如何,如果您想在此处使用
*
,您可以执行以下任一操作:

df['a'] * s                    # convert df to series

df * pd.DataFrame(s).values    # convert s to dataframe then to array

df * s.values.reshape(3,1)     # convert s to numpy array
第一个是很明显的,你只是把事情设置成两个系列,然后事情按照你想要的方式进行。请注意,这比将两者转换为数据帧更容易,因为在相乘系列时只需要对齐索引(轴=0),但在相乘数据帧时需要对齐索引和列(轴=1)。尽管您可以通过给系列指定与要乘以的数据帧列相同的名称来解决这个问题

第二种和第三种方法更有趣、更一般。它们通过转换为numpy数组来摆脱索引。这样做可以让您自由地做很多不同的事情,但请记住,这可能是危险的,因为您会显式地忽略索引,这意味着由您来确保它们正确排列

另外请注意,一般情况下,您可以使用
.values.shape
来更好地了解尝试乘法、除法等操作时的维度。通常,当这些操作失败时,快速检查形状会告诉您原因