Python 展开DataFrame列中的整数范围
我有一个数据框,看起来像:Python 展开DataFrame列中的整数范围,python,python-3.x,pandas,dataframe,Python,Python 3.x,Pandas,Dataframe,我有一个数据框,看起来像: d = {'value': ['a','b','c','d','e','f','g', 'h'],\ 'id' : ['0101', '0208', '0103', '0405', '0105,0116,0117', '0108-0110', '0231, 0232, 0133-0150', '0155, 0152-0154, 0151']} df = pd.DataFrame(d) >>>
d = {'value': ['a','b','c','d','e','f','g', 'h'],\
'id' : ['0101', '0208', '0103', '0405', '0105,0116,0117',
'0108-0110', '0231, 0232, 0133-0150', '0155, 0152-0154, 0151']}
df = pd.DataFrame(d)
>>>
value id
0 a 0101
1 b 0208
2 c 0103
3 d 0405
4 e 0105
5 e 0116
6 e 0117
7 f 0108
8 f 0109
9 f 0110
10 g 0231, 0232, 0133-0150
11 h 0155, 0152-0154, 0151
但我需要扩展这些ID,使每一行都是一个数字,因此看起来更像:
value id
0 a 0101
1 b 0208
2 c 0103
3 d 0405
4 e 0105
5 e 0116
6 e 0117
7 f 0108
8 f 0109
9 f 0110
10 g ...
其中,每行在ID分组的位置重复(范围扩展,对于小于4位的ID保留前导零)
我已经到了
df['id'].str.split(",")
df['id'].str.contains("-")
但我想不出一个好办法来做这件事。有人能帮忙吗 您可以编写一个小例程来展平范围,然后根据需要重复原始值
from itertools import chain
flattened = []
for x in df['id'].str.split(r',\s*'):
flattened.append([])
for y in x:
if '-' in y:
start, end = pd.to_numeric(y.split('-'))
flattened[-1].extend(pd.RangeIndex(start, end+1))
else:
flattened[-1].append(int(y))
repeats = [len(f) for f in flattened]
事实证明,即使对于更大的数据,这也是非常有效的
df_ = df
df = pd.concat([df_] * 1000, ignore_index=True)
%timeit flatten(df) # Function running code above.
244 ms ± 15.5 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
以下是一种方法:
s = (df['id'].str.split(r"[, ]|[-]")
.apply(pd.Series)
.stack()
.reset_index(level=1, drop=True))
df.drop('id', axis =1).join(s.to_frame()).reset_index(drop=True)
value 0
0 a 0101
1 b 0208
2 c 0103
3 d 0405
4 e 0105
5 e 0116
6 e 0117
7 f 0108
8 f 0109
9 f 0110
10 g 0231
11 g 0232
12 g 0133
13 g 0150
14 h 0155
15 h 0152
16 h 0154
17 h 0151
我认为您的示例已损坏或不完整是的,很抱歉,还需要扩展范围,已编辑虽然技术上没有错误,
apply(pd.Series)
已知存在一些严重的性能问题。。。并与stack复合。。。不要让简洁欺骗你:-)是的,我知道:)。如果数据框较大,我还将添加一个更有效的解决方案。数据框不大(~1000行),但我还需要填写范围,即0133-0150变为0133、0134、0135。。。我明白了。将修改当前的解决方案我很欣赏这是多么的干净和可读,但目前还不能完全解决问题,尽管@NixonTanks对此表示感谢,但我无法真正阅读或理解它,但它工作得非常好。谢谢,而且似乎很有效。此解决方案适用于n>2列吗?由于以下错误,我似乎无法使其适用于我的实际示例:ValueError:int()的文本无效,以10为基数:“0 0 0…\n1 0 0…\n2 0…”
@BenJones它目前适合于两列,但您始终可以打开一个后续问题,询问如何推广它(提示:尝试使用df.apply
)在我打开一个新问题之前,我已经修复了df_flat=pd.DataFrame中的硬编码字典部分({
…等,但看不出问题出在哪里,哪一行是需要应用的部分?很多appreciated@BenJones正则表达式以逗号和可选空格分隔。在给出的解释中,您的错误对我来说仍然没有意义。最好的做法是打开一个新的Q。。。 :)
s = (df['id'].str.split(r"[, ]|[-]")
.apply(pd.Series)
.stack()
.reset_index(level=1, drop=True))
df.drop('id', axis =1).join(s.to_frame()).reset_index(drop=True)
value 0
0 a 0101
1 b 0208
2 c 0103
3 d 0405
4 e 0105
5 e 0116
6 e 0117
7 f 0108
8 f 0109
9 f 0110
10 g 0231
11 g 0232
12 g 0133
13 g 0150
14 h 0155
15 h 0152
16 h 0154
17 h 0151