很可能您可以使用更通用的方法,但这对我有用。请注意,这是基于您的特定示例的许多假设和约束。
test_dict = {'col_1': ['1 A, 2 B, 3 C', '2 B, 4 C', '1 B, 2 C, 4 D']}
df = pd.DataFrame(test_dict)
首先,我们将 df 拆分为初始列:
df2 = df.col_1.str.split(pat=',', expand=True)
结果:
0 1 2
0 1 A 2 B 3 C
1 2 B 4 C None
2 1 B 2 C 4 D
接下来,(第一个假设)我们需要确保以后可以使用' ' 作为分隔符来提取列。为了做到这一点,我们需要从每个字符串中删除所有开始和结尾的空格
func = lambda x: pd.Series([i.strip() for i in x])
df2 = df2.astype(str).apply(func, axis=1)
接下来,我们需要获取唯一列的列表。为此,我们首先从每个单元格中提取列名:
func = lambda x: pd.Series([i.split(' ')[1] for i in x if i != 'None'])
df3 = df2.astype(str).apply(func, axis=1)
结果:
0 1 2
0 A B C
1 B C NaN
2 B C D
然后创建一个包含在您的 DataFrame 中的唯一列 ['A', 'B', 'C', 'D'] 的列表:
columns_list = pd.unique(df3[df3.columns].values.ravel('K'))
columns_list = [x for x in columns_list if not pd.isna(x)]
并使用这些列创建一个空的基本数据框,这些列将用于分配相应的值:
result_df = pd.DataFrame(columns=columns_list)
准备工作完成后,我们可以为每一行分配列值,并使用pd.concat 将它们合并回一个 DataFrame:
result_list = []
result_list.append(result_df) # Adding the empty base table to ensure the columns are present
for row in df2.iterrows():
result_object = {} # dict that will be used to represent each row in source DataFrame
for column in columns_list:
for value in row[1]: # row is returned in the format of tuple where first value is row_index that we don't need
if value != 'None':
if value.split(' ')[1] == column: # Checking for a correct column to assign
result_object[column] = [value]
result_list.append(pd.DataFrame(result_object)) # Adding dicts per row
一旦生成了 DataFrames 列表,我们就可以使用pd.concat 将其放在一起:
final_df = pd.concat(result_list, ignore_index=True) # ignore_index will rebuild the index for the final_df
结果将是:
A B C D
0 1 A 2 B 3 C NaN
1 NaN 2 B 4 C NaN
2 NaN 1 B 2 C 4 D
我不认为这是最优雅和最有效的方法,但它会产生你需要的结果