构建3D Pandas数据框
我在用Pandas构建一个3D数据框时遇到了困难。我想要的结构大概是这样的:
A B C
start end start end start end ...
7 20 42 52 90 101
11 21 213 34
56 74 9 45
45 12
其中,A
、B
等是最上层的描述符,而start
和end
是子描述符。后面的数字是成对出现的,而且A
、B
等的成对数量是不一样的。注意,A
有四对,B
只有一对,而C
有三对。
我不太确定该如何继续构建这个数据框。修改这个例子并没有得到我想要的结果:
import numpy as np
import pandas as pd
A = np.array(['one', 'one', 'two', 'two', 'three', 'three'])
B = np.array(['start', 'end']*3)
C = [np.random.randint(10, 99, 6)]*6
df = pd.DataFrame(zip(A, B, C), columns=['A', 'B', 'C'])
df.set_index(['A', 'B'], inplace=True)
df
结果是:
C
A B
one start [22, 19, 16, 20, 63, 54]
end [22, 19, 16, 20, 63, 54]
two start [22, 19, 16, 20, 63, 54]
end [22, 19, 16, 20, 63, 54]
three start [22, 19, 16, 20, 63, 54]
end [22, 19, 16, 20, 63, 54]
有没有办法把
补充:我C
的结构很重要。它看起来像这样:
C = [[7,11,56,45], [20,21,74,12], [42], [52], [90,213,9], [101, 34, 45]]
而我想要的输出就是最上面的那个。它表示在某个序列中的子序列的起始和结束点(A
、B
、C
是不同的序列)。根据序列本身的不同,符合我所寻找的条件的子序列数量也不同。因此,A
、B
等的起始:结束对的数量也各不相同。
3 个回答
4
你难道不能直接用一个面板吗?
import numpy as np
import pandas as pd
A = ['one', 'two' ,'three']
B = ['start','end']
C = [np.random.randint(10, 99, 2)]*6
df = pd.DataFrame(C,columns=B )
p={}
for a in A:
p[a]=df
panel= pd.Panel(p)
print panel['one']
14
正如@Aaron在上面的评论中提到的,面板(panels)已经被淘汰了。此外,@tlnagy提到他的数据集将来可能会扩展到超过三维。
这听起来很适合使用xarray这个包,它可以处理任意多个维度的数组,并且这些数组都有明确的标签。Pandas和xarray之间的转换支持非常强大,而面板已经被淘汰,推荐使用xarray。
问题的初始设置。
import numpy as np
A = np.array([[7,11,56,45], [20,21,74,12]]).T
B = np.array([[42], [52]]).T
C = np.array([[90,213,9], [101, 34, 45]]).T
然后你可以这样创建一个三维的xarray.DataArray对象:
import xarray
output_as_dataarray = xarray.concat(
[
xarray.DataArray(
X,
dims=["record", "edge"],
coords={"record": range(X.shape[0]), "edge": ["start", "end"]},
)
for X in (A, B, C)
],
dim="descriptor",
).assign_coords(descriptor=["A", "B", "C"])
我们把三个二维的numpy数组转换成xarray.DataArray对象,然后在一个新的维度上把它们连接在一起。
我们的输出看起来是这样的:
<xarray.DataArray (descriptor: 3, record: 4, edge: 2)>
array([[[ 7., 20.],
[ 11., 21.],
[ 56., 74.],
[ 45., 12.]],
[[ 42., 52.],
[ nan, nan],
[ nan, nan],
[ nan, nan]],
[[ 90., 101.],
[213., 34.],
[ 9., 45.],
[ nan, nan]]])
Coordinates:
* record (record) int64 0 1 2 3
* edge (edge) <U5 'start' 'end'
* descriptor (descriptor) <U1 'A' 'B' 'C'
18
首先,我觉得你需要用C来表示缺失的值。
In [341]: max_len = max(len(sublist) for sublist in C)
In [344]: for sublist in C:
...: sublist.extend([np.nan] * (max_len - len(sublist)))
In [345]: C
Out[345]:
[[7, 11, 56, 45],
[20, 21, 74, 12],
[42, nan, nan, nan],
[52, nan, nan, nan],
[90, 213, 9, nan],
[101, 34, 45, nan]]
然后,把它转换成一个numpy数组,进行转置,再和列一起传给DataFrame的构造函数。
In [288]: C = np.array(C)
In [289]: df = pd.DataFrame(data=C.T, columns=pd.MultiIndex.from_tuples(zip(A,B)))
In [349]: df
Out[349]:
one two three
start end start end start end
0 7 20 42 52 90 101
1 11 21 NaN NaN 213 34
2 56 74 NaN NaN 9 45
3 45 12 NaN NaN NaN NaN