pandas系列可以作为列而非行吗?

0 投票
2 回答
1123 浏览
提问于 2025-04-18 18:00

这个问题看起来可能有点小题大做,但其实是个真实的问题。简单来说,我想把一个序列当作一列来处理,而不是一行。我觉得这样更直观,尽管从技术上讲,序列不能被严格划分为行和列,但一维的numpy数组是可以的。下面是个例子:

df = pd.DataFrame( { 'a' : [5,3,1],
                     'b' : [4,6,2],
                     'c' : [2,4,9] } )

df['rowsum'] = df.sum(1)

In [31]: df
Out[31]: 
   a  b  c  rowsum
0  5  4  2      11
1  3  6  4      13
2  1  2  9      12

我只是想按行计算百分比(也就是说每一行的总和为1)。我想这样做:

df.iloc[:,0:3] / df.rowsum

在numpy中,这样做是没问题的(通过reshape),因为你可以把行总和变成列向量或行向量。但在这里,我不能对序列进行reshape,也不能对df.rowsum使用T。看起来数据框(dataframe)可以转置,但序列(series)却不行。下面的代码可以正常工作(还有其他几种解决方案)。在numpy中可以很自然地实现,但那样就需要先转换成数组,然后再转换回数据框。

In [32]: ( df.iloc[:,0:3].T / df.rowsum ).T
Out[32]: 
          a         b         c
0  0.454545  0.363636  0.181818
1  0.230769  0.461538  0.307692
2  0.083333  0.166667  0.750000

如果这看起来很简单,我感到抱歉,但能够以直观的方式在代码中处理行和列是很重要的。所以我的问题就是:我能否让一个序列像列向量一样工作,而不是像行向量那样?

另外,似乎在列上这样做是没问题的,这让我觉得不太一致。

df.iloc[:,0] / df.rowsum

在这种情况下,pandas似乎是在对两个列数组进行逐元素的除法(因为显示的方式,即使行和列的区分是人为的)。但是当这个表达式的第一部分从数据框变成序列时,它似乎就从3x1变成了1x2。就像从序列变成数据框是一个隐式的转换操作?

也许换个角度思考会更好:

all( dist.iloc[:,:10].index == dist.rowsum.index )
Out[1526]: True

这里的索引是对齐的,为什么pandas在序列/序列广播和数据框/序列广播时似乎对索引的处理不同?还是说我完全想错了?!

2 个回答

1

试试看

df.iloc[:, 0:3].div(df.rowsum, axis=0)

看看这是不是你想要的。

2

试试这个

df.apply(lambda x:x/x[3], axis = 1)

        a          b           c    rowsum
0   0.454545    0.363636    0.181818    1
1   0.230769    0.461538    0.307692    1
2   0.083333    0.166667    0.750000    1

如果你不需要行总和这一列,可以使用

df.apply(lambda x:x/sum(x), axis = 1) #with your original dataFrame

撰写回答