将 DataFrame 或 Series 列表转换为一个堆叠的 DataFrame(或 Series)
Posted
技术标签:
【中文标题】将 DataFrame 或 Series 列表转换为一个堆叠的 DataFrame(或 Series)【英文标题】:Convert DataFrame or Series of lists into one stacked DataFrame (or Series) 【发布时间】:2018-04-19 20:03:54 【问题描述】:有一个由列表组成的DataFrame
(或Series
),如下所示:
df = pd.DataFrame([[[1,3], [2,3,4], [1,4,2,5]]], columns=['A', 'B', 'C']).T
print(df)
输出:
0
A [1, 3]
B [2, 3, 4]
C [1, 4, 2, 5]
我怎样才能把它变成
0
A 1
A 2
B 2
B 3
B 4
C 1
C 4
C 2
C 5
我尝试使用apply()
,但效果不佳。我可以隐式转换吗?我还尝试将所有数字提取为 [('A', 1), ('A', 3), ..]
的元组 from_records()
,但我也无法做到这一点。
我想我可以这样做:
pd.DataFrame.from_records(df[0].map(lambda x: [(0, v) for v in x]).sum())
但我不知道如何访问索引。注意(0, v)
实际上应该类似于(x.index, v)
。
【问题讨论】:
【参考方案1】:需要展平列中的值,然后按len
的lists
索引repeat
:
df = pd.DataFrame(0:np.concatenate(df.iloc[:, 0].values.tolist()),
index=df.index.repeat(df[0].str.len()))
from itertools import chain
df=pd.DataFrame(0:list(chain.from_iterable(df.iloc[:, 0].values.tolist())),
index=df.index.repeat(df[0].str.len()))
print (df)
0
A 1
A 3
B 2
B 3
B 4
C 1
C 4
C 2
C 5
时间安排:
np.random.seed(456)
N = 100000
a = [list(range(np.random.randint(5, 20))) for _ in range(N)]
L = list('abcdefghijklmno')
df = pd.DataFrame(0:a, index=np.random.choice(L, size=N))
print (df)
In [348]: %timeit pd.DataFrame(0:np.concatenate(df.iloc[:, 0].values.tolist()), index=df.index.repeat(df[0].str.len()))
1 loop, best of 3: 218 ms per loop
In [349]: %timeit pd.DataFrame(0:list(chain.from_iterable(df[0].values.tolist())), index=df.index.repeat(df[0].str.len()))
1 loop, best of 3: 388 ms per loop
In [350]: %timeit pd.DataFrame(df.iloc[:, 0].tolist(), index=df.index).stack().reset_index(level=1, drop=1).to_frame().astype(int)
1 loop, best of 3: 384 ms per loop
【讨论】:
我已经用一个使用from_records()
的示例更新了我的问题,但问题是当我使用map()
时我无法访问每个元素的实际索引......任何想法如果它可以这样工作?
嗯,这是不可能的:(
@displayname 请注意,我的回答涉及完整性,所以如果您有任何性能问题,请考虑查看 jezrael 的第一个选项 :-)
@cᴏʟᴅsᴘᴇᴇᴅ 感谢您的提示。事实上,我在那里遇到了性能问题。我也会看看 jezrael 的答案。
@displayname - 我对其进行了测试,对于更大的数据帧来说,第一个解决方案是更快的。还添加了时间来回答。【参考方案2】:
使用pd.DataFrame
+ stack
+ reset_index
+ to_frame
:
df = pd.DataFrame(df.iloc[:, 0].tolist(), index=df.index)\
.stack().reset_index(level=1, drop=1).to_frame()
df
0
A 1.0
A 3.0
B 2.0
B 3.0
B 4.0
C 1.0
C 4.0
C 2.0
C 5.0
【讨论】:
以上是关于将 DataFrame 或 Series 列表转换为一个堆叠的 DataFrame(或 Series)的主要内容,如果未能解决你的问题,请参考以下文章
从 panda DataFrame 创建一个 pd.Series 列表
TypeError: to_append 应该是 Series 或 Series 的列表/元组,得到 DataFrame