我有一个大约9000个数据集,其Territory范围的格式为[1-5,10-99,100-115],我想扩展数据,并在提供的数据集中将行扩展为该格式。
我的第一个想法可能是循环遍历“ Terri”系列并通过pd.series(range(i,100))运行它,但这不会创建以下输出。
感谢帮助。
import pandas as pd
d={'Peril':['Fire','Wind'],'Terri':[1-5,6-10],'Premium':[100,200]}
output={'Peril':['Fire','Fire','Fire','Fire','Fire','Wind','Wind','Wind','Wind','Wind'],'Terri':[1,2,3,4,5,6,7,8,9,10],'Premium':[100,100,100,100,100,200,200,200,200,200]}
df=pd.DataFrame(data=d)
expected_output=pd.DataFrame(data=output)
答案 0 :(得分:4)
使用几个帮助列表理解,然后使用pandas.index.repeat
,DataFrame.assign
和numpy.hstack
:
import numpy as np
import pandas as pd
ranges = [np.arange(s, e+1) for s, e in [list(map(int, x)) for x in df.Terri.str.split('-')]]
lens = [len(x) for x in ranges]
df_new = df.loc[df.index.repeat(lens)].assign(Terri=np.hstack(ranges))
[出]
Peril Terri Premium
0 Fire 1 100
0 Fire 2 100
0 Fire 3 100
0 Fire 4 100
0 Fire 5 100
1 Wind 6 200
1 Wind 7 200
1 Wind 8 200
1 Wind 9 200
1 Wind 10 200
供参考,ranges
如下:
[array([1, 2, 3, 4, 5]), array([ 6, 7, 8, 9, 10])]
lens
如下:
[5, 5]
答案 1 :(得分:2)
假设Terri
包含字符串范围,而不是进行减法运算,则可以创建一个范围范围的DataFrame,然后stack
可以受益于join
对公共索引的访问扩展原始框架。
u = df['Terri'].str.split('-', expand=True).astype(int).values
j = pd.DataFrame(
[np.arange(start, stop+1) for start, stop in u]
)
j.stack().reset_index(1, drop=True).to_frame('Terri')
df.drop('Terri', 1).join(f)
Peril Premium Terri
0 Fire 100 1
0 Fire 100 2
0 Fire 100 3
0 Fire 100 4
0 Fire 100 5
1 Wind 200 6
1 Wind 200 7
1 Wind 200 8
1 Wind 200 9
1 Wind 200 10
由于stack
的行为将删除空值,因此您的范围不必是统一的长度。
答案 2 :(得分:1)
唯一可行的方法是,如果您要启动DataFrame的Terri
列是字符串:
d={'Peril':['Fire','Wind'],'Terri':['1-5','6-10'],'Premium':[100,200]}
df = pd.DataFrame(d)
print(df)
# Peril Terri Premium
#0 Fire 1-5 100
#1 Wind 6-10 200
如果您在Terri
的{{1}}列中拆分了字符串,则可以将其用作-
的输入,除了需要在终止值上添加一个包括端点。为了简化操作,您可以定义自己的范围函数:
range
现在,您可以拆分列,应用def myRange(a, b):
return range(a, b+1)
函数,并堆叠结果:
myRange
最后将此结果与原始DataFrame结合起来
:temp = pd.DataFrame(
df['Terri'].str.split("-")\
.apply(lambda x: pd.Series(myRange(*map(int, x))))\
.stack()\
.reset_index(level=1, drop=True),
columns=["Terri"]
)
print(temp)
# Terri
#0 1
#0 2
#0 3
#0 4
#0 5
#1 6
#1 7
#1 8
#1 9
#1 10
同一件事,简明扼要:
print(df.drop(["Terri"], axis=1).join(temp))
# Peril Premium Terri
#0 Fire 100 1
#0 Fire 100 2
#0 Fire 100 3
#0 Fire 100 4
#0 Fire 100 5
#1 Wind 200 6
#1 Wind 200 7
#1 Wind 200 8
#1 Wind 200 9
#1 Wind 200 10
答案 3 :(得分:0)
如果[1-5,6-10]
实际上是['1-5','6-10']
,则下面的代码可以工作:
new_df = []
for row in df.iterrows():
rng = row[1]['Terri']
rng = rng.split('-')
start, end = int(rng[0]), int(rng[1])
for n in range(start, end+1):
new_row = {
'Peril': row[1]['Peril'],
'Terri': n,
'Premium': row[1]['Premium'],
}
new_df.append(new_row)
output = pd.DataFrame(new_df)