根据pandas中的特定条件拆分以逗号分隔的列
Split a column which is separated by comma based on certain condition in pandas
我有一个数据框
df = pd.DataFrame([["A","a*k,x*k,z,c*m,r,s,f*f,e*d"], ["B","h*t,y,a,w*b,Z,c*b,i*t,f*f"]], columns=["id","c1"])
我想在以下条件下拆分由逗号分隔的 c1 列:
- 只保留那些有 * 的字符串
- 如果 * 之后有重复字母则不考虑 2ns 字符串取下一个。
- 保留唯一的第 3 个字符串并将它们拆分为 * 并制作 2 个单独的列
示例:
对于 c1 中的第一行,
- z,r,s 没有 *,所以删除它们
- 在a*k和x *k中,k是重复的,所以保留第一个
- 因此前 3 位将是 a*k、c *m、f *f,拆分它并生成 2 列 c2、a、c、f 和 c3 k、m、f。
预期输出:
df_out = pd.DataFrame([["A","a*k,x*k,z,c*m,r,s,f*f,e*d","a,c,f","k,m,f"], ["B","h*t,y,a,w*b,Z,c*b,i*b,f*f","h,w,f","t,b,f"]], columns=["id","c1","c2","c3"])
怎么做?
您可以使用 pd.Series.str.extractall
和 GroupBy.apply
来删除重复项并获取前 3 个字符串。
out = df["c1"].str.extractall(r"(.)\*(.)").groupby(level=0)
df[["c2", "c3"]] = out.apply(
lambda x: x.drop_duplicates(subset=1).head(3).agg(",".join)
)
# df
id c1 c2 c3
0 A a*k,x*k,z,c*m,r,s,f*f,e*d a,c,f k,m,f
1 B h*t,y,a,w*b,Z,c*b,i*t,f*f h,w,f t,b,f
首先定义一个函数来生成2个新列:
def newCols(lst):
return pd.Series(filter(lambda tt: tt.find('*') >= 0, lst))\
.str.split('*', expand=True)\
.rename(columns={0: 'c2', 1: 'c3'})\
.drop_duplicates(subset='c3').iloc[:3]\
.apply(lambda col: ','.join(col))
然后生成结果为:
result = df.join(df.c1.str.split(',').apply(newCols))
结果是:
id c1 c2 c3
0 A a*k,x*k,z,c*m,r,s,f*f,e*d a,c,f k,m,f
1 B h*t,y,a,w*b,Z,c*b,i*t,f*f h,w,f t,b,f
newCols
中的处理步骤
pd.Series(filter(lambda tt: tt.find('*') >= 0, lst))
- 创建
来自包含星号的元素的 Series。
str.split('*', expand=True)
- 将其转换为 DataFrame。
rename(columns={0: 'c2', 1: 'c3'})
- 将列重命名为 'c2' 和 'c3'.
drop_duplicates(subset='c3')
- 删除重复行(具有相同的 c3)。
iloc[:3]
- 仅取 3 个初始行。
apply(lambda col: ','.join(col)
- 将每一列连接成一个字符串。
尝试将它们作为“不断扩展的代码”来执行,on:
lst = ['a*k', 'x*k', 'z', 'c*m', 'r', 's', 'f*f', 'e*d']
(第一个源行的结果)。
我有一个数据框
df = pd.DataFrame([["A","a*k,x*k,z,c*m,r,s,f*f,e*d"], ["B","h*t,y,a,w*b,Z,c*b,i*t,f*f"]], columns=["id","c1"])
我想在以下条件下拆分由逗号分隔的 c1 列:
- 只保留那些有 * 的字符串
- 如果 * 之后有重复字母则不考虑 2ns 字符串取下一个。
- 保留唯一的第 3 个字符串并将它们拆分为 * 并制作 2 个单独的列
示例: 对于 c1 中的第一行,
- z,r,s 没有 *,所以删除它们
- 在a*k和x *k中,k是重复的,所以保留第一个
- 因此前 3 位将是 a*k、c *m、f *f,拆分它并生成 2 列 c2、a、c、f 和 c3 k、m、f。
预期输出:
df_out = pd.DataFrame([["A","a*k,x*k,z,c*m,r,s,f*f,e*d","a,c,f","k,m,f"], ["B","h*t,y,a,w*b,Z,c*b,i*b,f*f","h,w,f","t,b,f"]], columns=["id","c1","c2","c3"])
怎么做?
您可以使用 pd.Series.str.extractall
和 GroupBy.apply
来删除重复项并获取前 3 个字符串。
out = df["c1"].str.extractall(r"(.)\*(.)").groupby(level=0)
df[["c2", "c3"]] = out.apply(
lambda x: x.drop_duplicates(subset=1).head(3).agg(",".join)
)
# df
id c1 c2 c3
0 A a*k,x*k,z,c*m,r,s,f*f,e*d a,c,f k,m,f
1 B h*t,y,a,w*b,Z,c*b,i*t,f*f h,w,f t,b,f
首先定义一个函数来生成2个新列:
def newCols(lst):
return pd.Series(filter(lambda tt: tt.find('*') >= 0, lst))\
.str.split('*', expand=True)\
.rename(columns={0: 'c2', 1: 'c3'})\
.drop_duplicates(subset='c3').iloc[:3]\
.apply(lambda col: ','.join(col))
然后生成结果为:
result = df.join(df.c1.str.split(',').apply(newCols))
结果是:
id c1 c2 c3
0 A a*k,x*k,z,c*m,r,s,f*f,e*d a,c,f k,m,f
1 B h*t,y,a,w*b,Z,c*b,i*t,f*f h,w,f t,b,f
newCols
中的处理步骤pd.Series(filter(lambda tt: tt.find('*') >= 0, lst))
- 创建 来自包含星号的元素的 Series。str.split('*', expand=True)
- 将其转换为 DataFrame。rename(columns={0: 'c2', 1: 'c3'})
- 将列重命名为 'c2' 和 'c3'.drop_duplicates(subset='c3')
- 删除重复行(具有相同的 c3)。iloc[:3]
- 仅取 3 个初始行。apply(lambda col: ','.join(col)
- 将每一列连接成一个字符串。
尝试将它们作为“不断扩展的代码”来执行,on:
lst = ['a*k', 'x*k', 'z', 'c*m', 'r', 's', 'f*f', 'e*d']
(第一个源行的结果)。