解除 Pandas 系列的嵌套(爆炸)
- 2025-02-11 09:50:00
- admin 原创
- 42
问题描述:
我有:
df = pd.DataFrame({'col1': ['asdf', 'xy', 'q'], 'col2': [1, 2, 3]})
col1 col2
0 asdf 1
1 xy 2
2 q 3
我想从 中的字符串中取出每个字母col1
与 中的每个元素整数的“组合积” col2
。即:
col1 col2
0 a 1
1 s 1
2 d 1
3 f 1
4 x 2
5 y 2
6 q 3
当前方法:
from itertools import product
pieces = []
for _, s in df.iterrows():
letters = list(s.col1)
prods = list(product(letters, [s.col2]))
pieces.append(pd.DataFrame(prods))
pd.concat(pieces)
还有更有效的解决方法吗?
解决方案 1:
使用list
+str.join
和np.repeat
-
pd.DataFrame(
{
'col1' : list(''.join(df.col1)),
'col2' : df.col2.values.repeat(df.col1.str.len(), axis=0)
})
col1 col2
0 a 1
1 s 1
2 d 1
3 f 1
4 x 2
5 y 2
6 q 3
可以轻松实现任意数量列的通用解决方案,而无需对解决方案进行太多改变 -
i = list(''.join(df.col1))
j = df.drop('col1', 1).values.repeat(df.col1.str.len(), axis=0)
df = pd.DataFrame(j, columns=df.columns.difference(['col1']))
df.insert(0, 'col1', i)
df
col1 col2
0 a 1
1 s 1
2 d 1
3 f 1
4 x 2
5 y 2
6 q 3
表现
df = pd.concat([df] * 100000, ignore_index=True)
# MaxU's solution
%%timeit
df.col1.str.extractall(r'(.)') \n .reset_index(level=1, drop=True) \n .join(df['col2']) \n .reset_index(drop=True)
1 loop, best of 3: 1.98 s per loop
# piRSquared's solution
%%timeit
pd.DataFrame(
[[x] + b for a, *b in df.values for x in a],
columns=df.columns
)
1 loop, best of 3: 1.68 s per loop
# Wen's solution
%%timeit
v = df.col1.apply(list)
pd.DataFrame({'col1':np.concatenate(v.values),'col2':df.col2.repeat(v.apply(len))})
1 loop, best of 3: 835 ms per loop
# Alexander's solution
%%timeit
pd.DataFrame([(letter, i)
for letters, i in zip(df['col1'], df['col2'])
for letter in letters],
columns=df.columns)
1 loop, best of 3: 316 ms per loop
%%timeit
pd.DataFrame(
{
'col1' : list(''.join(df.col1)),
'col2' : df.col2.values.repeat(df.col1.str.len(), axis=0)
})
10 loops, best of 3: 124 ms per loop
我尝试对 Vaishali 进行计时,但在这个数据集上花费的时间太长了。
解决方案 2:
pd.DataFrame([(letter, i)
for letters, i in zip(df['col1'], df['col2'])
for letter in letters],
columns=df.columns)
解决方案 3:
list
来自:-)的技巧
df.col1=df.col1.apply(list)
df
Out[489]:
col1 col2
0 [a, s, d, f] 1
1 [x, y] 2
2 [q] 3
pd.DataFrame({'col1':np.concatenate(df.col1.values),'col2':df.col2.repeat(df.col1.apply(len))})
Out[490]:
col1 col2
0 a 1
0 s 1
0 d 1
0 f 1
1 x 2
1 y 2
2 q 3
解决方案 4:
In [86]: df.col1.str.extractall(r'(.)') \n .reset_index(level=1, drop=True) \n .join(df['col2']) \n .reset_index(drop=True)
Out[86]:
0 col2
0 a 1
1 s 1
2 d 1
3 f 1
4 x 2
5 y 2
6 q 3
解决方案 5:
再来一个:)
df.set_index('col2').col1.apply(lambda x: pd.Series(list(x))).stack()\n.reset_index(1,drop = True).reset_index(name = 'col1')
col2 col1
0 1 a
1 1 s
2 1 d
3 1 f
4 2 x
5 2 y
6 3 q
解决方案 6:
使用列表理解和巧妙解包的通用解决方案:
pd.DataFrame(
[[x] + b for a, *b in df.values for x in a],
columns=df.columns
)
col1 col2
0 a 1
1 s 1
2 d 1
3 f 1
4 x 2
5 y 2
6 q 3
解决方案 7:
使用 Explode(pandas>=0.25)
df = pd.DataFrame({'col1': ['asdf', 'xy', 'q'], 'col2': [1, 2, 3]})
df.col1=df.col1.apply(list)
df = df.explode('col1')
结果:
col1 col2
0 a 1
0 s 1
0 d 1
0 f 1
1 x 2
1 y 2
2 q 3
解决方案 8:
您还可以尝试itertools.chain和itertools.repeat函数来实现类似的结果。
举个例子
import pandas as pd
from itertools import chain, repeat
d = {'col1': ['asdf', 'xy', 'q'], 'col2': [1, 2, 3]}
expanded_d = {
"col1": list(chain(*[list(item) for item in d["col1"]])),
"col2": list(chain(*[list(repeat(d["col2"][idx], len(list(d["col1"][idx])))) for idx in range(len(d["col1"])) ]))
}
result = pd.DataFrame(data=expanded_d)
col1 col2
0 a 1
1 s 1
2 d 1
3 f 1
4 x 2
5 y 2
6 q 3
希望有帮助。
相关推荐
热门文章
项目管理软件有哪些?
热门标签
云禅道AD