按行数据帧分割
Row-wise DataFrame segmentation
给定以下数据框:
df = pd.DataFrame(data={'item': [1, 2, 3, 4], 'start':[0.0, 2.0, 8.0, 6.0],
'end': [2.0, 6.0, 8.0, 14.0]})
如何通过将区间 'start' - 'end' 分割成 2 的倍数来快速逐行扩展上述数据帧?
对于上面的例子,生成的数据帧应该是
Out=
item start end
1 0.0 2.0
2 2.0 4.0
2 4.0 6.0
3 8.0 8.0
4 6.0 8.0
4 8.0 10.0
4 10.0 12.0
4 12.0 14.0
性能对我来说至关重要,因为我有数百万行要检查。
对于那些不需要分段的行,我已经使用布尔索引过滤了整个数据框。这是一个很大的加速但是,在其余的行上,我应用了 'for loop' 并制作了我一直附加的正确长度的数据帧。不幸的是,性能不足以处理数百万行。
期待高手解答!
您可以编写一个函数,该函数 return 是扩展开始和结束时间的 DataFrame。在这个例子中,我 groupby item
因为我不确定你是否可以 return 来自 apply
的 DataFrame 而不是先将它分组。
def convert(row):
start = row.start.values[0]
end = row.end.values[0]
if start == end:
return pd.DataFrame([[start, end]], columns=['start', 'end'])
else:
return pd.DataFrame({'start': np.arange(start, end, 2),
'end':np.arange(start + 2, end + 2, 2)},
columns=['start', 'end'])
df1=df.groupby('item').apply(convert)
df1.index = df1.index.droplevel(1)
df1.reset_index()
item start end
0 1 0.0 2.0
1 2 2.0 4.0
2 2 4.0 6.0
3 3 8.0 8.0
4 4 6.0 8.0
5 4 8.0 10.0
6 4 10.0 12.0
7 4 12.0 14.0
从原始数据帧开始:
import pandas as pd
import numpy as np
df = pd.DataFrame(data={'item': [1, 2, 3, 4], 'start':[0.0, 2.0, 8.0, 6.0],
'end': [2.0, 6.0, 10.0, 14.0]})
然后,运行下面的代码:
lengths = pd.Series([1, 2, 1, 4]) # For the example, I just created this array,
# but obviously I would use the mod function to
# determine the number of segments to create
# Row below elongates the dataframe according to the array 'lengths'
df = df.reindex(np.repeat(df.index.values, lengths), method='ffill')
df['start'] += pd.Series(df.groupby(level=0).cumcount()*2.0)
df['end'] = df['start'] + 2.0
print df
请注意,初始数据帧包含错误。项目“3”需要 'start=8.0' 和 'end=10.0'。
由于使用了 pandas Cython 函数,我相信这种方法非常快。当然,仍然对其他可能性持开放态度。
给定以下数据框:
df = pd.DataFrame(data={'item': [1, 2, 3, 4], 'start':[0.0, 2.0, 8.0, 6.0],
'end': [2.0, 6.0, 8.0, 14.0]})
如何通过将区间 'start' - 'end' 分割成 2 的倍数来快速逐行扩展上述数据帧?
对于上面的例子,生成的数据帧应该是
Out=
item start end
1 0.0 2.0
2 2.0 4.0
2 4.0 6.0
3 8.0 8.0
4 6.0 8.0
4 8.0 10.0
4 10.0 12.0
4 12.0 14.0
性能对我来说至关重要,因为我有数百万行要检查。 对于那些不需要分段的行,我已经使用布尔索引过滤了整个数据框。这是一个很大的加速但是,在其余的行上,我应用了 'for loop' 并制作了我一直附加的正确长度的数据帧。不幸的是,性能不足以处理数百万行。
期待高手解答!
您可以编写一个函数,该函数 return 是扩展开始和结束时间的 DataFrame。在这个例子中,我 groupby item
因为我不确定你是否可以 return 来自 apply
的 DataFrame 而不是先将它分组。
def convert(row):
start = row.start.values[0]
end = row.end.values[0]
if start == end:
return pd.DataFrame([[start, end]], columns=['start', 'end'])
else:
return pd.DataFrame({'start': np.arange(start, end, 2),
'end':np.arange(start + 2, end + 2, 2)},
columns=['start', 'end'])
df1=df.groupby('item').apply(convert)
df1.index = df1.index.droplevel(1)
df1.reset_index()
item start end
0 1 0.0 2.0
1 2 2.0 4.0
2 2 4.0 6.0
3 3 8.0 8.0
4 4 6.0 8.0
5 4 8.0 10.0
6 4 10.0 12.0
7 4 12.0 14.0
从原始数据帧开始:
import pandas as pd
import numpy as np
df = pd.DataFrame(data={'item': [1, 2, 3, 4], 'start':[0.0, 2.0, 8.0, 6.0],
'end': [2.0, 6.0, 10.0, 14.0]})
然后,运行下面的代码:
lengths = pd.Series([1, 2, 1, 4]) # For the example, I just created this array,
# but obviously I would use the mod function to
# determine the number of segments to create
# Row below elongates the dataframe according to the array 'lengths'
df = df.reindex(np.repeat(df.index.values, lengths), method='ffill')
df['start'] += pd.Series(df.groupby(level=0).cumcount()*2.0)
df['end'] = df['start'] + 2.0
print df
请注意,初始数据帧包含错误。项目“3”需要 'start=8.0' 和 'end=10.0'。
由于使用了 pandas Cython 函数,我相信这种方法非常快。当然,仍然对其他可能性持开放态度。