![](/img/trans.png)
[英]Split string column based on delimiter and create columns for each value in Pyspark
[英]String split using a delimiter on pandas column to create new columns
我有一个 dataframe 有这样的列
Col1
1 A, 2 B, 3 C
2 B, 4 C
1 B, 2 C, 4 D
我用过.str.split(',', expand=True)
,结果是这样的
0 | 1 | 2
1 A | 2 B | 3 C
2 B | 4 C | None
1 B | 2 C | 4 D
我想要实现的是得到这个:
Col A| Col B| Col C| Col D
1 A | 2 B | 3 C | None
None | 2 B | 4 C | None
None | 1 B | 2 C | 4 D
我被卡住了,如何将新列格式化为这样?
我们试试看:
# split and explode
s = df['Col1'].str.split(', ').explode()
# create new multi-level index
s.index = pd.MultiIndex.from_arrays([s.index, s.str.split().str[-1].tolist()])
# unstack to reshape
out = s.unstack().add_prefix('Col ')
细节:
# split and explode
0 1 A
0 2 B
0 3 C
1 2 B
1 4 C
2 1 B
2 2 C
2 4 D
Name: Col1, dtype: object
# create new multi-level index
0 A 1 A
B 2 B
C 3 C
1 B 2 B
C 4 C
2 B 1 B
C 2 C
D 4 D
Name: Col1, dtype: object
# unstack to reshape
Col A Col B Col C Col D
0 1 A 2 B 3 C NaN
1 NaN 2 B 4 C NaN
2 NaN 1 B 2 C 4 D
您很可能可以使用更通用的方法,但这对我有用。 请注意,这是基于您的特定示例的许多假设和约束。
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)]
并创建一个空的基础 dataframe 与那些将用于分配相应值的列: 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
生成 DataFrame 列表后,我们可以使用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
我不认为这是最优雅和最有效的方法,但它会产生你需要的结果
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.