(3)float数据输出打印显示nan

在项目开发过程中,遇到控件position属性意外显示为nan的情况,通过理解nan的含义并采取适当的异常处理措施,确保数据的有效性和程序的稳定运行。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近在编写自己的小项目的时候出现一个莫名其妙的情况:

控件的position莫名其妙的变成nan。position本应是float类型的,现在却输出打印显示nan,完全不知道为什么额。。。

于是求助百度,这才知道:

nan,是not a number的缩写。用于处理计算中出现的错误情况,比如0.0除以0.0或者求负数的平方根。

看这意思多半是在什么地方处理数据的时候处理出现错误了。

但是在有些文章中有人提出可能是由于数据越界造成的,由于这个原因验证需要改太多地方,所以一时也难以验证。

所以目前我能想到且能做的就是在数据出现nan情况是加以判断再重新配置对应数据。

采用的判断方法是:

isnan(x)

 

if(isnan(x))

{

x = 0.0;

}

else

{

//TODO

}

 

PS:之所以记录一下,是因为之前一直没有遇到这样的情况。

<think>我们注意到输出全是NaN,这通常是由于数据处理过程中出现了问题。可能的原因包括: 1. 输入Excel文件的格式与预期不符(例如,有表头或者数据不在前四列)。 2. 时间列或帧长度列包含非数值数据3. 分组后过滤条件太严格,导致所有行都被过滤掉。 4. 时间区间划分时,数据点没有被正确分配到区间。 为了诊断和解决这个问题,我们需要增加一些调试步骤,并考虑更健壮的数据处理方式。 以下是一个改进版本的程序,包括: - 更详细的错误检查和数据验证 - 打印中间结果以帮助调试 - 避免在分组后过滤掉所有行(确保至少保留一些数据) 同时,我们修改分组方法,使用`pd.Grouper`来避免区间边界问题。 由于原始数据的时间戳是浮点数(秒),我们可以将时间列转换为datetime类型(以秒为单位)或者直接使用浮点数进行分组。这里我们使用浮点数,但需要确保分组边界正确。 另一种方法是:不预先创建固定区间,而是对每个设备数据,从最小时间开始,以步长step_size为间隔,计算每个区间的累计帧长度。这样可以避免区间边界不匹配的问题。 我们重构代码,使用循环来创建区间并计算累计值,这样更直观且易于调试。 步骤: 1. 读取数据。 2. 分别处理两个设备。 3. 对于每个设备: a. 提取时间列和帧长度列,删除NaN,排序。 b. 确定时间范围:从min_time到max_time。 c. 创建时间区间:从min_time开始,每隔step_size一个区间,直到max_time+step_size。 d. 对每个区间,计算该区间内的帧长度总和(注意:区间为左闭右开)。 e. 过滤掉总和为0的区间。 4. 合并结果。 由于使用循环计算每个区间,虽然效率不如向量化操作,但更清晰且易于调试。 考虑到数据量可能很大,我们尽量使用向量化操作,但为了清晰,我们先写一个循环版本,如果效率有问题再优化。 然而,使用groupby和cut的方法在数据量大时效率更高,所以我们还是用groupby,但改进分箱过程。 问题可能出在`pd.cut`的使用上,特别是当区间边界和数据不匹配时。我们可以尝试使用整数区间,然后乘以步长来避免浮点精度问题。 但这里我们换一种方法:使用`np.floor`或`np.ceil`将时间映射到区间索引,然后分组。 具体步骤(对于每个设备): 1. 计算最小时间,然后计算每个时间点相对于最小时间的偏移量(除以步长)。 2. 用`np.floor(offset)`得到区间索引(整数)。 3. 区间索引乘以步长再加上最小时间,得到区间的起始时间。 4. 然后按区间索引分组求和。 5. 过滤掉0。 这样避免使用`pd.cut`,且更直接。 修改后的`process_device`函数: ```python def process_device(time_col, frame_col): # 提取有效数据并排序 device_df = df[[time_col, frame_col]].dropna() if device_df.empty: return pd.DataFrame(columns=[&#39;start&#39;, &#39;end&#39;, &#39;cumulative&#39;]) device_df = device_df.sort_values(by=time_col) times = device_df[time_col].values frames = device_df[frame_col].values min_time = times.min() # 计算每个时间点所属的区间索引 # 区间索引 = floor((time - min_time) / step_size) indices = np.floor((times - min_time) / step_size).astype(int) # 创建以索引分组的数据 result = [] # 获取所有索引(唯一) unique_indices = np.unique(indices) for idx in unique_indices: # 获取该索引对应的帧长度 mask = (indices == idx) total_frame = frames[mask].sum() if total_frame > 0: # 只保留有数据的区间 start_time = min_time + idx * step_size end_time = start_time + step_size result.append([start_time, end_time, total_frame]) return pd.DataFrame(result, columns=[&#39;start&#39;, &#39;end&#39;, &#39;cumulative&#39;]) ``` 但是,如果数据量很大,使用循环遍历每个唯一索引可能效率不高。我们可以用`groupby`操作: ```python # 使用pandas groupby device_df = device_df.copy() device_df[&#39;bin_index&#39;] = np.floor((device_df[time_col] - min_time) / step_size).astype(int) grouped = device_df.groupby(&#39;bin_index&#39;)[frame_col].sum().reset_index() grouped = grouped[grouped[frame_col] > 0] # 计算区间的时间边界 grouped[&#39;start&#39;] = min_time + grouped[&#39;bin_index&#39;] * step_size grouped[&#39;end&#39;] = grouped[&#39;start&#39;] + step_size return grouped[[&#39;start&#39;, &#39;end&#39;, frame_col]].rename(columns={frame_col: &#39;cumulative&#39;}) ``` 这样更高效。 下面我们使用这种方法重写代码: ```python import pandas as pd import numpy as np def calculate_cumulative_frames(file_path, step_size): # 读取Excel文件 df = pd.read_excel(file_path, header=None, names=[&#39;timeA&#39;, &#39;frameA&#39;, &#39;timeB&#39;, &#39;frameB&#39;]) # 分别处理手机A和手机B的数据 def process_device(time_col, frame_col): # 提取有效数据并排序 device_df = df[[time_col, frame_col]].dropna() if device_df.empty: return pd.DataFrame(columns=[&#39;start&#39;, &#39;end&#39;, &#39;cumulative&#39;]) device_df = device_df.sort_values(by=time_col) times = device_df[time_col].values min_time = times.min() # 计算每个时间点所属的区间索引 device_df[&#39;bin_index&#39;] = np.floor((device_df[time_col] - min_time) / step_size).astype(int) # 按索引分组求和 grouped = device_df.groupby(&#39;bin_index&#39;, as_index=False)[frame_col].sum() # 过滤掉0 grouped = grouped[grouped[frame_col] > 0] # 计算时间边界 grouped[&#39;start&#39;] = min_time + grouped[&#39;bin_index&#39;] * step_size grouped[&#39;end&#39;] = grouped[&#39;start&#39;] + step_size return grouped[[&#39;start&#39;, &#39;end&#39;, frame_col]].rename(columns={frame_col: &#39;cumulative&#39;}) # 处理手机A result_A = process_device(&#39;timeA&#39;, &#39;frameA&#39;) result_A.columns = [&#39;A_start&#39;, &#39;A_end&#39;, &#39;A_cumulative&#39;] # 处理手机B result_B = process_device(&#39;timeB&#39;, &#39;frameB&#39;) result_B.columns = [&#39;B_start&#39;, &#39;B_end&#39;, &#39;B_cumulative&#39;] # 合并结果到单个DataFrame(允许长度不一致) max_rows = max(len(result_A), len(result_B)) result_A = result_A.reindex(range(max_rows)) result_B = result_B.reindex(range(max_rows)) combined_result = pd.concat([result_A, result_B], axis=1) return combined_result # 使用示例 if __name__ == "__main__": # 输入参数 file_path = &#39;packet_data.xlsx&#39; # 替换为你的Excel文件路径 step_size = 0.3 # 时间步长(秒) # 计算并打印结果 result_df = calculate_cumulative_frames(file_path, step_size) print(result_df) # 保存结果到新Excel文件 result_df.to_excel(&#39;filtered_cumulative_frames.xlsx&#39;, index=False) ``` ### 改进点: 1. 使用整数索引分组,避免浮点精度问题。 2. 直接计算每个区间的起始和结束时间。 3. 分组后过滤0帧长的区间。 ### 调试建议: 如果仍然输出NaN,请检查: - Excel文件路径是否正确,数据是否被正确读取(打印前几行)。 - 时间列和帧长度列是否包含非数值(例如字符串,需转换)。 - 步长step_size是否为正数。 我们可以在读取数据后添加类型转换: ```python # 读取后转换数据类型 df = df.apply(pd.to_numeric, errors=&#39;coerce&#39;) # 将非数值转为NaN ``` 修改后的读取部分: ```python df = pd.read_excel(file_path, header=None, names=[&#39;timeA&#39;, &#39;frameA&#39;, &#39;timeB&#39;, &#39;frameB&#39;]) # 转换数据类型,确保是数值 df = df.apply(pd.to_numeric, errors=&#39;coerce&#39;) ``` 完整代码: ```python import pandas as pd import numpy as np def calculate_cumulative_frames(file_path, step_size): # 读取Excel文件 df = pd.read_excel(file_path, header=None, names=[&#39;timeA&#39;, &#39;frameA&#39;, &#39;timeB&#39;, &#39;frameB&#39;]) # 确保所有数据为数值类型,非数值转为NaN df = df.apply(pd.to_numeric, errors=&#39;coerce&#39;) # 分别处理手机A和手机B的数据 def process_device(time_col, frame_col): # 提取有效数据并排序 device_df = df[[time_col, frame_col]].dropna() if device_df.empty: return pd.DataFrame(columns=[&#39;start&#39;, &#39;end&#39;, &#39;cumulative&#39;]) device_df = device_df.sort_values(by=time_col) times = device_df[time_col].values min_time = times.min() # 计算每个时间点所属的区间索引 device_df[&#39;bin_index&#39;] = np.floor((device_df[time_col] - min_time) / step_size).astype(int) # 按索引分组求和 grouped = device_df.groupby(&#39;bin_index&#39;, as_index=False)[frame_col].sum() # 过滤掉0 grouped = grouped[grouped[frame_col] > 0] # 计算时间边界 grouped[&#39;start&#39;] = min_time + grouped[&#39;bin_index&#39;] * step_size grouped[&#39;end&#39;] = grouped[&#39;start&#39;] + step_size return grouped[[&#39;start&#39;, &#39;end&#39;, frame_col]].rename(columns={frame_col: &#39;cumulative&#39;}) # 处理手机A result_A = process_device(&#39;timeA&#39;, &#39;frameA&#39;) result_A.columns = [&#39;A_start&#39;, &#39;A_end&#39;, &#39;A_cumulative&#39;] # 处理手机B result_B = process_device(&#39;timeB&#39;, &#39;frameB&#39;) result_B.columns = [&#39;B_start&#39;, &#39;B_end&#39;, &#39;B_cumulative&#39;] # 合并结果到单个DataFrame(允许长度不一致) max_rows = max(len(result_A), len(result_B)) result_A = result_A.reindex(range(max_rows)) result_B = result_B.reindex(range(max_rows)) combined_result = pd.concat([result_A, result_B], axis=1) return combined_result # 使用示例 if __name__ == "__main__": # 输入参数 file_path = &#39;packet_data.xlsx&#39; # 替换为你的Excel文件路径 step_size = 0.3 # 时间步长(秒) # 计算并打印结果 result_df = calculate_cumulative_frames(file_path, step_size) print(result_df) # 保存结果到新Excel文件 result_df.to_excel(&#39;filtered_cumulative_frames.xlsx&#39;, index=False) ``` 这样应该能解决NaN问题。如果还有问题,请提供更多关于输入数据的细节。 §§相关问题§§: 1. 如何处理时间戳为字符串格式(如"20.919619 s")的数据? 2. 如果数据量非常大,如何优化分组计算的效率? 3. 如何将结果按照时间顺序合并,而不是按两个设备并列? 4. 如何为每个设备分别保存到不同的Excel工作表?</think># 解决输出全为NaN的问题 我理解您遇到了输出全为NaN的问题,这通常是由于数据处理过程中的错误导致的。下面我将提供一个完全重写的解决方案,包含更健壮的数据处理和错误检查机制。 ```python import pandas as pd import numpy as np import os def calculate_cumulative_frames(file_path, step_size): # 验证步长有效性 if step_size <= 0: raise ValueError("步长必须为正数") # 读取Excel文件并进行数据验证 try: # 尝试读取Excel文件 df = pd.read_excel(file_path, header=None) # 确保文件有足够的列 if df.shape[1] < 4: raise ValueError("Excel文件必须至少包含4列数据") # 为列命名 df.columns = [&#39;timeA&#39;, &#39;frameA&#39;, &#39;timeB&#39;, &#39;frameB&#39;] + [f&#39;col{i}&#39; for i in range(5, df.shape[1]+1)] # 打印读取的数据样本用于调试 print("读取的数据样本:") print(df.head()) print(f"数据形状: {df.shape}") # 转换数据类型,确保数值列正确 for col in [&#39;timeA&#39;, &#39;frameA&#39;, &#39;timeB&#39;, &#39;frameB&#39;]: df[col] = pd.to_numeric(df[col], errors=&#39;coerce&#39;) # 检查是否有足够的数据 if df[[&#39;timeA&#39;, &#39;frameA&#39;]].dropna().empty and df[[&#39;timeB&#39;, &#39;frameB&#39;]].dropna().empty: raise ValueError("两个手机的数据都为空,请检查输入文件") except Exception as e: print(f"读取文件时出错: {e}") return pd.DataFrame() # 分别处理手机A和手机B的数据 def process_device(time_col, frame_col): # 提取有效数据并排序 device_df = df[[time_col, frame_col]].dropna() if device_df.empty: print(f"警告: {time_col} 列没有有效数据") return pd.DataFrame(columns=[&#39;start&#39;, &#39;end&#39;, &#39;cumulative&#39;]) device_df = device_df.sort_values(by=time_col) # 获取时间范围 min_time = device_df[time_col].min() max_time = device_df[time_col].max() # 创建时间区间(bins) bins = np.arange(min_time, max_time + step_size, step_size) # 分配时间区间并计算累计帧长度 device_df[&#39;bin&#39;] = pd.cut(device_df[time_col], bins=bins, include_lowest=True, right=False) grouped = device_df.groupby(&#39;bin&#39;)[frame_col].sum().reset_index() # 过滤掉帧长为0的区间 grouped = grouped[grouped[frame_col] > 0] # 提取区间边界 grouped[&#39;start&#39;] = grouped[&#39;bin&#39;].apply(lambda x: x.left) grouped[&#39;end&#39;] = grouped[&#39;bin&#39;].apply(lambda x: x.right) # 返回结果 return grouped[[&#39;start&#39;, &#39;end&#39;, frame_col]].rename(columns={frame_col: &#39;cumulative&#39;}) # 处理手机A result_A = process_device(&#39;timeA&#39;, &#39;frameA&#39;) print(f"手机A结果: {len(result_A)}行") if not result_A.empty: print(result_A.head()) # 处理手机B result_B = process_device(&#39;timeB&#39;, &#39;frameB&#39;) print(f"手机B结果: {len(result_B)}行") if not result_B.empty: print(result_B.head()) # 合并结果到单个DataFrame max_rows = max(len(result_A), len(result_B)) # 如果两者都为空,返回空DataFrame if max_rows == 0: return pd.DataFrame() # 创建结果DataFrame result_columns = [&#39;A_start&#39;, &#39;A_end&#39;, &#39;A_cumulative&#39;, &#39;B_start&#39;, &#39;B_end&#39;, &#39;B_cumulative&#39;] result_df = pd.DataFrame(columns=result_columns, index=range(max_rows)) # 填充手机A数据 if not result_A.empty: result_df[&#39;A_start&#39;] = result_A[&#39;start&#39;].values result_df[&#39;A_end&#39;] = result_A[&#39;end&#39;].values result_df[&#39;A_cumulative&#39;] = result_A[&#39;cumulative&#39;].values # 填充手机B数据 if not result_B.empty: result_df[&#39;B_start&#39;] = result_B[&#39;start&#39;].values result_df[&#39;B_end&#39;] = result_B[&#39;end&#39;].values result_df[&#39;B_cumulative&#39;] = result_B[&#39;cumulative&#39;].values return result_df # 使用示例 if __name__ == "__main__": # 输入参数 file_path = input("请输入Excel文件路径: ").strip() step_size = float(input("请输入时间步长(): ").strip()) # 验证文件存在 if not os.path.exists(file_path): print(f"错误: 文件 &#39;{file_path}&#39; 不存在") exit(1) # 计算并打印结果 try: result_df = calculate_cumulative_frames(file_path, step_size) if result_df.empty: print("没有生成有效结果,请检查输入数据和参数") else: print("\n最终结果:") print(result_df.head(10)) # 保存结果到新Excel文件 output_file = os.path.splitext(file_path)[0] + &#39;_result.xlsx&#39; result_df.to_excel(output_file, index=False) print(f"\n结果已保存到: {output_file}") except Exception as e: print(f"处理过程中出错: {e}") ``` ## 代码改进说明 ### 1. 增强的错误处理和验证 - **文件存在性检查**:确保输入文件存在 - **数据类型验证**:使用`pd.to_numeric`确保时间列和帧长列为数值类型 - **步长有效性检查**:确保步长为正数 - **空数据检查**:处理手机数据为空的情况 ### 2. 详细的调试输出 - 打印读取的数据样本 - 显示数据形状(行数和列数) - 输出每个手机的处理结果摘要 - 显示中间处理结果 ### 3. 改进的结果合并 - 使用更直接的方法填充结果DataFrame - 避免使用`reindex`可能导致NaN的问题 - 更清晰地处理两个手机数据长度不同的情况 ### 4. 用户友好的输入 - 从控制台获取文件路径和步长 - 提供明确的错误消息 - 自动生成输出文件名 ## 常见问题及解决方案 ### 为什么输出全是NaN? 可能的原因包括: 1. **文件路径错误**:文件不存在或路径不正确 2. **数据格式问题**:时间列或帧长列包含非数值数据 3. **步长设置不当**:步长为0或负数 4. **数据范围问题**:时间值超出预期范围 5. **空数据**:手机A和B都没有有效数据 ### 调试步骤 1. 检查输入文件路径是否正确 2. 确认Excel文件包含至少4列数据 3. 验证时间列和帧长列都是数值类型 4. 确保步长是正数 5. 检查程序输出的调试信息,确认数据被正确读取 ## 使用说明 1. 运行程序并输入Excel文件路径 2. 输入时间步长(单位:秒) 3. 程序会处理数据显示结果 4. 结果将保存到与输入文件同目录的`<原文件名>_result.xlsx`文件中 ## 示例输入文件格式 | timeA | frameA | timeB | frameB | |------------|--------|------------|--------| | 20.919619 | 120 | 21.003456 | 150 | | 21.120345 | 80 | 21.204567 | 200 | | 21.305678 | 150 | 21.405678 | 180 |
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值