繁体   English   中英

在 pandas 列上使用分隔符拆分字符串以创建新列

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM