熊猫何时默认默认播放系列和数据帧?

时间:2019-02-17 08:13:39

标签: python pandas numpy-broadcasting

在尝试回答this question时,我遇到了一些(对我而言)好奇的事情。

说我要比较一系列形状(10,)与形状df(10,10):

np.random.seed(0)
my_ser = pd.Series(np.random.randint(0, 100, size=10))
my_df = pd.DataFrame(np.random.randint(0, 100, size=100).reshape(10,10))
my_ser > 10 * my_df
如预期的那样,p产生df形状的矩阵(10,10)。比较似乎是逐行的。

但是考虑这种情况:

df = pd.DataFrame({'cell1':[0.006209, 0.344955, 0.004521, 0, 0.018931, 0.439725, 0.013195, 0.009045, 0, 0.02614, 0],
              'cell2':[0.048043, 0.001077, 0,0.010393, 0.031546, 0.287264, 0.016732, 0.030291, 0.016236, 0.310639,0], 
              'cell3':[0,0,0.020238, 0, 0.03811, 0.579348, 0.005906, 0,0,0.068352, 0.030165],
              'cell4':[0.016139, 0.009359, 0,0,0.025449, 0.47779, 0, 0.01282, 0.005107, 0.004846, 0],
              'cell5': [0,0,0,0.012075, 0.031668, 0.520258, 0,0,0,2.728218, 0.013418]})
i = 0
df.iloc[:,i].shape
>(11,)
(10 * df.drop(df.columns[i], axis=1)).shape
>(11,4)
(df.iloc[:,i] > (10 * df.drop(df.columns[i], axis=1))).shape
>(11,15)

据我所知,这里的熊猫与df播出了系列赛。为什么会这样?

所需行为可以通过以下方式获得:

(10 * df.drop(df.columns[i], axis=1)).lt(df.iloc[:,i], axis=0).shape
>(11,4)

pd.__version__
'0.24.0'

2 个答案:

答案 0 :(得分:7)

正在发生的事情是使用固有数据对齐的熊猫。熊猫几乎总是在行索引或列标题的索引上对齐数据。这是一个简单的示例:

s1 = pd.Series([1,2,3], index=['a','b','c'])
s2 = pd.Series([2,4,6], index=['a','b','c'])
s1 + s2
#Ouput as expected:
a    3
b    6
c    9
dtype: int64

现在,让我们运行其他几个具有不同索引的示例:

s2 = pd.Series([2,4,6], index=['a','a','c'])
s1 + s2
#Ouput
a    3.0
a    5.0
b    NaN
c    9.0
dtype: float64

笛卡尔积与索引重复发生,并且匹配为NaN + value = NaN。

而且,没有匹配的索引:

s2 = pd.Series([2,4,6], index=['e','f','g'])
s1 + s2
#Output
a   NaN
b   NaN
c   NaN
e   NaN
f   NaN
g   NaN
dtype: float64

因此,在您的第一个示例中,您正在创建具有匹配的默认范围索引的pd.Series和pd.DataFrame,因此比较是按预期进行的。在第二个示例中,您将列标题['cell2','cell3','cell4','cell5']与默认范围索引进行比较,该默认范围索引返回所有15列且不匹配,所有值均为False,NaN比较返回False。

答案 1 :(得分:4)

底线,Pandas将每个系列值与标题与值索引匹配的列进行比较。第二个示例中的索引为0..10,列名称为cell1..4,因此没有列名称匹配,您只需追加新列即可。实质上,这是将系列视为具有索引作为列标题的数据框。


如果您将序列的长度设置为比列数长,那么您实际上可以在第一个示例中看到熊猫所做的部分工作:

>>> my_ser = pd.Series(np.random.randint(0, 100, size=20))
>>> my_df
    0   1   2   3   4
0   9  10  27  45  71
1  39  61  85  97  44
2  34  34  88  33   5
3  36   0  75  34  69
4  53  80  62   8  61
5   1  81  35  91  40
6  36  48  25  67  35
7  30  29  33  18  17
8  93  84   2  69  12
9  44  66  91  85  39
>>> my_ser
0     92
1     36
2     25
3     32
4     42
5     14
6     86
7     28
8     20
9     82
10    68
11    22
12    99
13    83
14     7
15    72
16    61
17    13
18     5
19     0
dtype: int64
>>> my_ser>my_df
      0      1      2      3      4      5      6      7      8      9   \
0   True   True  False  False  False  False  False  False  False  False
1   True  False  False  False  False  False  False  False  False  False
2   True   True  False  False   True  False  False  False  False  False
3   True   True  False  False  False  False  False  False  False  False
4   True  False  False   True  False  False  False  False  False  False
5   True  False  False  False   True  False  False  False  False  False
6   True  False  False  False   True  False  False  False  False  False
7   True   True  False   True   True  False  False  False  False  False
8  False  False   True  False   True  False  False  False  False  False
9   True  False  False  False   True  False  False  False  False  False

      10     11     12     13     14     15     16     17     18     19
0  False  False  False  False  False  False  False  False  False  False
1  False  False  False  False  False  False  False  False  False  False
2  False  False  False  False  False  False  False  False  False  False
3  False  False  False  False  False  False  False  False  False  False
4  False  False  False  False  False  False  False  False  False  False
5  False  False  False  False  False  False  False  False  False  False
6  False  False  False  False  False  False  False  False  False  False
7  False  False  False  False  False  False  False  False  False  False
8  False  False  False  False  False  False  False  False  False  False
9  False  False  False  False  False  False  False  False  False  False

请注意发生了什么-将92与第一列进行比较,因此您在93处得到一个False。然后将36与第二列进行比较,以此类推。如果系列长度与您的列数匹配,那么您就会得到预期的行为。

但是当您的系列较长时会发生什么?好了,您需要在数据框中添加一个新的假列以继续比较。它充满了什么?我没有找到任何文档,但是我的印象是它只填写False,因为没有可比较的内容。因此,您将获得额外的列以匹配序列长度,即全部False

但是您的示例呢?您没有得到11列,而是4 + 11 = 15!让我们进行另一个测试:

>>> my_df = pd.DataFrame(np.random.randint(0, 100, size=100).reshape(10,10),columns=[chr(i) for i in range(10)])
>>> my_ser = pd.Series(np.random.randint(0, 100, size=10))
>>> (my_df>my_ser).shape
(10, 20)

这一次我们得到了尺寸总和10 + 10 = 20,作为输出列的数量!

有什么区别?熊猫会将每个系列索引与匹配的列标题进行比较。在第一个示例中,my_sermy_df标题的索引匹配,因此将它们进行了比较。如果有多余的列-以上将发生。如果所有列的名称都不同,则序列索引不同,那么所有列都是多余的,您就会得到结果,在我的示例中,标题现在是字符,索引整数也发生了什么。