我有一个Pandas DataFrame,在列中有几个列表我想拆分。每个列表具有相同的长度,并且必须在相同的索引处进行拆分。
我现在使用的是here的建议,但我无法使它起作用:
import numpy as np
import pandas as pd
from itertools import chain
split_size = 2
def split_list(arr, keep_partial=False):
arrs = []
while len(arr) >= split_size:
sub = arr[:split_size]
arrs.append(sub)
arr = arr[split_size:]
if keep_partial:
arrs.append(arr)
return arrs
df = pd.DataFrame({'id': [1, 2, 3], 't': [[1,2,3,4], [1,2,3,4,5,6], [0,2]], 'v': [[0,-1,1,0], [0,-1,1,0,2,-2], [0,0]]})
def chainer(lst):
return list(chain.from_iterable(split_list(lst, split_size)))
def chain_col(col):
return col.apply(lambda x: chainer(x))
lens = df.t.apply(lambda x: len(split_list(x)))
pd.DataFrame({'id': np.repeat(df.id, lens), 't': chain_col(df.t), 'v': chain_col(df.v)})
问题在于它会重复每个 full 列表,而不是将它们分成几行。我认为问题在于chain.from_iterable
的用法,但如果没有它,我只会重复获取列表列表(即拆分列表),而不是将每个拆分列表都拆分到DataFrame中自己的行。
我的数据集不是很大(几千行),所以如果有更好的方法,我将很高兴学习。我看着explode
,但这似乎是根据单个列拆分数据集,我希望以相同的方式拆分多个列。
我想要的输出是id = 1
是
1. a row with t = [1,2] and v = [0,-1]
2. another row with t = [3,4] = [1,0]
理想情况下我将为每个“ id”添加一个子索引(例如1-> 1.1和1.2,这样我就可以区分它们),但这只是表面上的事情,而不是我的主要问题。
答案 0 :(得分:0)
IIUC,这是一种使用功能的方法,该功能将列表拆分为n个块,然后用applymap
拆分每个单元格,然后是explode
和implementation group: 'org.jpmml', name: 'jpmml-evaluator-spark', version: '1.0.0'
:
concat
def split_lists(l, n):
"""splits a list to n chunks"""
for i in range(0, len(l), n):
yield l[i:i + n]
def explode_multiple(x):
"""This will use the prev func,
explode each columns and concat them to a dataframe"""
m=x.applymap(lambda x: [*split_lists(x,2)])
m=pd.concat([m.explode(i).loc[:,i] for i in m.columns],axis=1).reset_index()
return m
explode_multiple(df.set_index('id')) #setting id as index since other columns have list
答案 1 :(得分:0)
explode
,pd.concat
和GroupBy
: 注意:此答案使用了仅explode
pandas>=0.25.0
方法
d1 = df.explode('t').drop(columns='v')
d2 = df.explode('v').drop(columns=['id', 't'])
df2 = pd.concat([d1,d2], axis=1)
df2
s = df2.groupby('id')['id'].cumcount()//2
final = df2.groupby(['id', s]).agg({'t':list,
'v':list}).reset_index(level=0)
final['id'] = final['id'].astype(str).str.cat('.'+final.groupby('id').cumcount().add(1).astype(str))
输出
id t v
0 1.1 [1, 2] [0, -1]
1 1.2 [3, 4] [1, 0]
0 2.1 [1, 2] [0, -1]
1 2.2 [3, 4] [1, 0]
2 2.3 [5, 6] [2, -2]
0 3.1 [0, 2] [0, 0]