使用pandas将两个序列相乘创建一个数据框。

7

假设我有两个pandas系列,系列A和系列B。如何创建一个数据框,其中所有这些值都相乘,即在左侧放置系列A,在顶部放置系列B。基本上与此概念相同,其中系列A将是左侧的黄色,系列B将是顶部的黄色,并且中间的所有值都将通过乘法填充:

http://www.google.co.uk/imgres?imgurl=http://www.vaughns-1-pagers.com/computer/multiplication-tables/times-table-12x12.gif&imgrefurl=http://www.vaughns-1-pagers.com/computer/multiplication-tables.htm&h=533&w=720&sz=58&tbnid=9B8R_kpUloA4NM:&tbnh=90&tbnw=122&zoom=1&usg=__meqZT9kIAMJ5b8BenRzF0l-CUqY=&docid=j9BT8tUCNtg--M&sa=X&ei=bkBpUpOWOI2p0AWYnIHwBQ&ved=0CE0Q9QEwBg

抱歉,可能应该补充说明我的两个序列长度不同。我现在收到一个错误消息,指出“矩阵未对齐”,因此我认为这就是问题所在。

你到目前为止尝试了什么?你可以编辑你的问题并添加一些代码、错误或结果。 - Theresa
5个回答

5

您可以使用矩阵乘法点积,但在此之前,您需要将Series转换为DataFrame(因为 Series上的dot方法实现了点积):

>>> B = pd.Series(range(1, 5))
>>> A = pd.Series(range(1, 5))
>>> dfA = pd.DataFrame(A)
>>> dfB = pd.DataFrame(B)
>>> dfA.dot(dfB.T)
   0  1   2   3
0  1  2   3   4
1  2  4   6   8
2  3  6   9  12
3  4  8  12  16

4

你可以通过对两个长度不等的Series进行广播,将每行(或列)的每个值与另一个Series相乘来创建一个DataFrame。例如:

> row = pd.Series(np.arange(1, 6), index=np.arange(1, 6))
> col = pd.Series(np.arange(1, 4), index=np.arange(1, 4))
> row.apply(lambda r: r * col)
   1   2   3
1  1   2   3
2  2   4   6
3  3   6   9
4  4   8  12
5  5  10  15

3

首先创建一个由1组成的DataFrame。然后在每个轴上依次进行广播乘法。

>>> s1 = Series([1,2,3,4,5])
>>> s2 = Series([10,20,30])
>>> df = DataFrame(1, index=s1.index, columns=s2.index)
>>> df
   0  1  2
0  1  1  1
1  1  1  1
2  1  1  1
3  1  1  1
4  1  1  1
>>>> df.multiply(s1, axis='index') * s2
    0    1    2
0  10   20   30
1  20   40   60
2  30   60   90
3  40   80  120
4  50  100  150

您需要使用 df.multiply 来指定系列将与行索引对齐。您可以使用普通乘法运算符 *,因为在 DataFrame 和 Series 之间进行乘法运算时,默认情况下是在列上匹配。


我认为这个方案最清晰,因为当你使用s1和s2的索引来定义ones dataframe(例如中的df)的行和列时,它是一个视觉提示,可以看出你使用了哪个序列作为行和哪个序列作为列,而且你可以逐步构建它并理解其工作原理。 - Nesha25

1

如果您有两个长度不同的系列,我认为这可能会让您走得更远。这似乎是一个非常手动的过程,但我想不出使用 pandas 或 NumPy 函数的其他方法。

>>>> a = Series([1, 3, 3, 5, 5])
>>>> b = Series([5, 10])

首先将您的行值a转换为DataFrame,并将此Series的副本制作成新的列形式,与您的列系列b中的值数量相同。
>>>> result = DataFrame(a)
>>>> for i in xrange(len(b)):
            result[i] = a
   0   1
0  1   1
1  3   3
2  3   3
3  5   5
4  5   5

你可以将你的系列 b 广播到你的数据框 result:
>>>> result = result.mul(b)
   0   1
0  5   10
1  15  30
2  15  30
3  25  50
4  25  50

在我选择的示例中,由于您的初始Series,您最终会得到重复的索引。我建议将索引保留为唯一标识符。这在编程上是有意义的,否则当您选择一个分配给多行的索引时,您将返回多个值。如果必须重新索引您的行标签和列标签,则可以使用以下函数:
>>>> result.columns = b
>>>> result.set_index(a)
   5   10
1  5   10
3  15  30
3  15  30
5  25  50
5  25  50

重复索引的示例:

>>>> result.loc[3]
   5   10
3  15  30
3  15  30

0
为了使用DataFrame.dot方法,您需要转置其中一个系列:
>>> a = pd.Series([1, 2, 3, 4])
>>> b = pd.Series([10, 20, 30])
>>> a.to_frame().dot(b.to_frame().transpose())
    0   1   2
0  10  20  30
1  20  40  60
2  30  60  90
3  40  80 120

还要确保系列的名称相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接