我希望有效地在DataFrame
上执行以下操作。 DataFrame
有一个特殊列,包含字符串,其中某些行有格式问题。 Naemly,就我而言,它有一个+
符号,分隔两个独立列的条目。
特别要考虑:
import pandas as pd
pd.DataFrame([ ['a', 0, 1 ], ['b+c', 2, 3 ],
['d+e', 4, 5 ], ['f', 6, 7 ] ])
打印:
0 1 2
0 a 0 1
1 b+c 2 3
2 d+e 4 5
3 f 6 7
我想将其转换为:
0 1 2
0 a 0 1
1 b 2 3
2 c 2 3
3 d 4 5
4 e 4 5
5 f 6 7
那就是"展开"存在+
符号的行,复制其他列。这可以通过循环遍历并使用正则表达式分配给新数据帧来完成,但我正在寻找一种更简单,更有效的方法。
编辑:最理想的是,该功能允许多个分隔符(+
符号)。也就是说,也转变
import pandas as pd
pd.DataFrame([ ['a', 0, 1 ], ['b+c', 2, 3 ],
['d+e+f', 4, 5 ], ['g', 6, 7 ] ])
到
0 1 2
0 a 0 1
1 b 2 3
2 c 2 3
3 d 4 5
4 e 4 5
5 f 4 5
6 g 6 7
答案 0 :(得分:3)
一种方法是将.str.split
与stack
和join
合并:
s = df[0].str.split("+", expand=True).stack()
s.index = s.index.droplevel(1)
result = s.to_frame().join(df.drop(0, axis=1)).reset_index(drop=True)
给了我
In [18]: result
Out[18]:
0 1 2
0 a 0 1
1 b 2 3
2 c 2 3
3 d 4 5
4 e 4 5
5 f 4 5
6 g 6 7
答案 1 :(得分:2)
我喜欢将其分解为numpy位并将数据帧重新组合在一起。
计划
location.pathname = '/home/home.html'
var fullUrl = location .protocol + "//" + location.host + "/home/home.html"
快吗?
确定它是!
如果您需要确保'+'
保持不变,我们最后可以v = df.values[:, 1:]
z = np.core.defchararray.split(df[0].values.astype(str), '+')
i = np.arange(len(z)).repeat([len(x) for x in z])
pd.DataFrame(np.column_stack([np.concatenate(z), v[i]]))
0 1 2
0 a 0 1
1 b 2 3
2 c 2 3
3 d 4 5
4 e 4 5
5 f 6 7
。这会导致性能下降,但仍然很快。
dtypes
答案 2 :(得分:1)
您需要将加号的第一列中的字符串拆分为列表,将每个列表重新转换为Series
对象,将Series
个对象堆叠为单个Series
,然后重置单级索引的索引,仅保留原始行标识符。
然后我们需要使用索引将此系列与原始DataFrame
连接起来,然后删除原始列。为方便起见,我将列命名为:
import pandas as pd
df = pd.DataFrame([['a', 0, 1], ['b+c', 2, 3], ['d+e+f', 4, 5], ['g', 6, 7]],
columns=list('ABC'))
s_A = df.A.str.split('+').apply(pd.Series).stack().reset_index(level=1, drop=True)
s_A.name = 'A_split'
pd.concat([df.drop('A', axis=1), s_A], axis=1)
# returns:
B C A_split
0 0 1 a
1 2 3 b
1 2 3 c
2 4 5 d
2 4 5 e
2 4 5 f
3 6 7 g
答案 3 :(得分:1)
如果您的问题特定于将每行拆分为两行或单独留下,您可以简单地收集要拆分的行,并将它们附加到您的数据帧:
import pandas as pd
df = pd.DataFrame([ ['a', 0, 1 ], ['b+c', 2, 3 ],
['d+e', 4, 5 ], ['f', 6, 7 ] ])
df_split = df[df[0].str.contains('\+')].copy()
df_split['new_col_name'] = df[0].str.extract('\+(.*)', expand = False)
df['new_col_name'] = df[0].str.extract('([^\+]*)', expand = False)
df.append(df_split) # required answer
如果行的排序很重要,您可以首先创建每个行号的列,例如df['no'] = list(range(len(df)))
,然后在最后做sort_values('no')
。