如何将可变长度列表的 Pandas DataFrame 列(或系列)转换为固定宽度的 DataFrame [重复]
Posted
技术标签:
【中文标题】如何将可变长度列表的 Pandas DataFrame 列(或系列)转换为固定宽度的 DataFrame [重复]【英文标题】:How to convert a Pandas DataFrame column (or Series) of variable-length lists to a DataFrame of fixed width [duplicate] 【发布时间】:2021-02-19 19:30:40 【问题描述】:我想将具有不同长度列表的 DataFrame 列(或 Series)转换为具有固定列数的 DataFrame。
DataFrame 将具有与最长列表一样多的列,而其他列表较短的值可以是 NaN 或任何值。
当数据以字符串形式出现时,str 模块允许这样做,str.split
中的选项 expand
。但我无法找到可变长度列表的等价物。
在我的示例中,列表中的类型是 int,但我们的想法是可以使用任何类型。这可以防止简单地将 Series 转换为 str 并应用提到的 expand
属性。
下面我展示了使用 str.split
函数运行带有列表的示例的代码,以及要转换的系列的最小示例。
我找到了一个使用 apply 的解决方案,如示例中所示,但速度极慢以至于没有用处。
import numpy as np
import pandas as pd
# Example with a list as a string
A = pd.DataFrame('lists': [
'[]',
'[360,460,160]',
'[360,1,2,3,4,5,6]',
'[10,20,30]',
'[100,100,100,100]',
],
'other': [1,2,3,4,5]
)
print(A['lists'].astype(str).str.strip('[]').str.split(',', expand=True))
# Example with actual lists
B = pd.DataFrame('lists': [
[],
[360,460,160],
[360,1,2,3,4,5,6],
[10,20,30],
[100,100,100,100],
],
'other': [1,2,3,4,5]
)
# Create and pre-fill expected columns
max_len = max(B['lists'].str.len())
for idx in range(max_len):
B[f'lists_idx'] = np.nan
# Use .apply to fill the columns
def expand_int_list(row, col, df):
for idx, item in enumerate(row[col]):
df.loc[row.name, f'col_idx'] = item
B.apply(lambda row: expand_int_list(row, 'lists', B), axis=1)
print(B)
输出:
0 1 2 3 4 5 6
0 None None None None None None
1 360 460 160 None None None None
2 360 1 2 3 4 5 6
3 10 20 30 None None None None
4 100 100 100 100 None None None
lists other lists_0 lists_1 lists_2 lists_3 \
0 [] 1 NaN NaN NaN NaN
1 [360, 460, 160] 2 360.0 460.0 160.0 NaN
2 [360, 1, 2, 3, 4, 5, 6] 3 360.0 1.0 2.0 3.0
3 [10, 20, 30] 4 10.0 20.0 30.0 NaN
4 [100, 100, 100, 100] 5 100.0 100.0 100.0 100.0
lists_4 lists_5 lists_6
0 NaN NaN NaN
1 NaN NaN NaN
2 4.0 5.0 6.0
3 NaN NaN NaN
4 NaN NaN NaN
编辑和最终解决方案:
使其他问题中找到的方法失败的重要信息是,在我的数据中,有时我有 None
而不是列表。
在这种情况下,使用tolist()
将再次生成一系列列表,Pandas 不允许使用B.loc[B[col].isna(), col] = []
将这些单元格设为空列表。
我找到的解决方案是只在非None的行中使用tolist()
,而concat
使用原始索引:
# Example with actual lists
B = pd.DataFrame('lists': [
[],
[360,460,160],
None,
[10,20,30],
[100,100,100,100],
],
'other': [1,2,3,4,5]
)
col = 'lists'
# I need to keep the index for the concat afterwards.
extended = pd.DataFrame(B.loc[~B[col].isna(), col].tolist(),
index=B.loc[~B[col].isna()].index)
extended = extended.add_prefix(f'col_')
B = pd.concat([B, extended], axis=1)
print(B)
输出:
lists other lists_0 lists_1 lists_2 lists_3
0 [] 1 NaN NaN NaN NaN
1 [360, 460, 160] 2 360.0 460.0 160.0 NaN
2 None 3 NaN NaN NaN NaN
3 [10, 20, 30] 4 10.0 20.0 30.0 NaN
4 [100, 100, 100, 100] 5 100.0 100.0 100.0 100.0
【问题讨论】:
这能回答你的问题吗? How to create a Pandas DataFrame from a list of lists with different lengths? 感谢@MayankPorwal 的建议,由于长度可变,我认为它不适用于我的情况,但原因是有时使用 None 而不是列表。我会更新问题。 【参考方案1】:如果将嵌套列表转换为列表并传递给DataFrame
构造函数,缺失值会像最长列表一样添加,然后DataFrame.add_prefix
并由DataFrame.join
附加到原始:
df = B.join(pd.DataFrame(B['lists'].tolist()).add_prefix('lists_'))
print (df)
lists other lists_0 lists_1 lists_2 lists_3 \
0 [] 1 NaN NaN NaN NaN
1 [360, 460, 160] 2 360.0 460.0 160.0 NaN
2 [360, 1, 2, 3, 4, 5, 6] 3 360.0 1.0 2.0 3.0
3 [10, 20, 30] 4 10.0 20.0 30.0 NaN
4 [100, 100, 100, 100] 5 100.0 100.0 100.0 100.0
lists_4 lists_5 lists_6
0 NaN NaN NaN
1 NaN NaN NaN
2 4.0 5.0 6.0
3 NaN NaN NaN
4 NaN NaN NaN
【讨论】:
感谢@jezrael 的回复。我之前尝试过 .tolist() 并认为由于可变长度列表而无法正常工作,但有时我有 None 而不是列表。我将更新问题并添加找到的解决方案,从您的回复开始。以上是关于如何将可变长度列表的 Pandas DataFrame 列(或系列)转换为固定宽度的 DataFrame [重复]的主要内容,如果未能解决你的问题,请参考以下文章