我最近将一个庞大的excel文件转换为pandas数据帧,该文件中填充了随机列的空单元格。结果数据帧因此有很长的NaN
段。
然而,在对数据帧进行一些操作之后,我在这里和那里创建了一些较小的NaN
串,以及我想保留的那些NaN
。所以我试着编写一个函数来创建一个由 足够大量的NaN 分隔的数字块的字典(所以输出只能由原始Excel文件缺少数据)。
我的代码:
def nan_stripper(data,bound):
newdict = {}
chunk = 0
i = 0
while i < len(data):
if ~np.isnan(data[i]):
newdict.setdefault('chunk ' + str(chunk),[]).append(data[i])
i += 1
continue
elif np.isnan(data[i]):
# Create clear buffer for next chunk of nan's
buffer = []
while np.isnan(data[i]):
buffer.append(data[i])
i += 1
# When stretch ends, append processed nan's if below selected bound,
# and prepare for next number segment.
if ~np.isnan(data[i]):
if len(buffer) < bound + 1:
newdict['chunk ' + str(chunk)].extend(buffer)
if len(buffer) >= bound + 1:
chunk += 1
return newdict
在这里进行测试,使用NaN
3的界限:
a = np.array([-1,1,2,3,np.nan,np.nan,np.nan,np.nan,4,5,np.nan,np.nan,7,8,9,10])
b = nan_stripper(a,3)
print(b)
{'chunk 0': [-1.0, 1.0, 2.0, 3.0],
'chunk 1': [4.0, 5.0, nan, nan, 7.0, 8.0, 9.0, 10.0]}
事情是,我不相信我的代码是有效的,因为我使用了一个奇怪的字典方法( found here ),以便将附加值附加到单个键。是否有任何我想要的简单优化,或者你们中的一些人是否已经采用了完全不同的方式?我觉得这不可能是最狡猾的方式。
提前谢谢。
与答案的比较: 在确定了我原来的方法和Paul Panzer的时间之后,这些是对那些感兴趣的人的结果。
答案 0 :(得分:1)
这是一个矢量化版本。它会滑动一个大小限制在数据上的窗口,保持当前的nan计数,并标记计数等于绑定的偏移量(即窗口仅包含nans的位置)。
然后,它将这些标记的一部分混合在一起,在边界处分裂并丢弃其他所有标记(仅包含纳米标记)。
import numpy as np
def nan_split(data, bound, make_dict=False):
data = np.asanyarray(data)
# find nans, convert boolean mask to int8 to enable basic arithmetic
m = np.isnan(data).view(np.int8)
# compute windowed sum (same as windowed nan count)
m[bound:] -= m[:-bound]
# find all all-nan window offsets
m = m.cumsum() == bound
# find offsets where it switches between all-nan and non all-nan
idx, = np.where(m[1:] != m[:-1])
# correct for window size and edge loss
idx[::2] += 2-bound
idx[1::2] += 1
# split
if make_dict:
return {f'chunk {i}': c
for i, c in enumerate(np.split(data, idx)[2*(idx[0]==0)::2])}
else:
return np.split(data, idx)[2*(idx[0]==0)::2]