Python数据分析:利用SNS数据计算电导率
import os
import pandas as pd
import numpy as np
from openpyxl import Workbook
from openpyxl.utils.dataframe import dataframe_to_rows
class SNSData:
def __init__(self, pandas_dir=''):
if os.path.isfile(pandas_dir):
self.path = pandas_dir
else:
raise FileNotFoundError('File not found:' + pandas_dir)
self.raw_data = pd.read_csv(self.path, encoding='utf-8')
self.regular_data = {'name': [], 'property': [], 'magnitude': [], 'phase': [], 'frequency': []}
self.freq_list = [1, 2, 3, 7, 11, 17, 23, 31, 43, 61, 89, 127, 179, 251, 349]
for it in self.freq_list:
self.regular_data['name'].extend(self.raw_data['name'])
self.regular_data['property'].extend(self.raw_data['property']) # 盐水考虑浓度属性,脑脊液不考虑, 在新数据中命名为盐水+浓度
self.regular_data['magnitude'].extend(self.raw_data[str(it) + 'kHz_mag'])
self.regular_data['phase'].extend(self.raw_data[str(it) + 'kHz_ang'])
for i in range(self.raw_data.shape[0]):
self.regular_data['frequency'].append(it)
self.regular_data['logFreq'] = np.log10(self.regular_data['frequency']) # 将频率以对数形式展现
self.regular_data['R'] = np.array(self.regular_data['magnitude']) * np.cos(
np.array(self.regular_data['phase']) * 3.14 / 180) # np.cos默认弧度
self.regular_data['X'] = np.array(self.regular_data['magnitude']) * np.sin(
np.array(self.regular_data['phase']) * 3.14 / 180)
self.regular_data['logMag'] = np.log10(self.regular_data['magnitude']) # 在bode图中,幅度也是用对数表示的
'''下面利用已知浓度盐水的R和电导率(conductivity)映射关系来得到待测物体的电导率'''
# 创建电导率空列表保持行数一致
self.regular_data['conductivity'] = [0] * self.raw_data.shape[0] * len(self.freq_list)
self.df = pd.DataFrame(self.regular_data)
self.generate_conductivity()
'''重新整理完数据后,整合至pandas数据帧,用get_df方法可以返回该pandas数据帧'''
def generate_conductivity(self):
'''
映射关系如下
利用给出的盐水和电导率表自己先写个映射关系
'''
conductivity_list = [976, 1987, 3850, 5650, 7450, 9238] # 该电导率列表对应浓度为0.1,0.5的盐水
concentration_list = [0.05, 0.10, 0.2, 0.3, 0.4, 0.50]
saline_real_dict = {} # 每个频率,每个浓度的盐水的实部,其中同浓度对应同一个电导率
# 在这里,首先过滤出同一个频率下的所有盐水的real part,然后对同一个浓度的realpart求平均值,这里有七个浓度,将七个平均值打包为一个列表,作为子列表添加入saline_real_list
for it in self.freq_list: # 对每一个频率
one_freq_saline_real_list = [] # 打包用的子列表
for con in concentration_list:
# 这里依次为0.05, 0.1, 0.2, 0., 0.4, 0.6的盐水的real part平均值
saline_concentration = 'saline' + format(con, '.2f')
filted_df = self.df[
self.df['frequency'].isin([it]) * self.df['name'].isin([saline_concentration])] # 筛选出该频率下浓度0.05的样本
avg = np.mean(filted_df['R']) # 求筛选出来的下R的平均值
one_freq_saline_real_list.append(avg)
saline_real_dict[it] = one_freq_saline_real_list # 每一个频率下都有了一个浓度对应的real part列表
# real part和电导率建立起映射关系,对于单个频率,one_freq_saline_real_list作为x轴,conductivity作为y轴,用np.interp方法, 寻找R对应的电导率
self.regular_data['conductivity'] += self.df['frequency'].isin([it]) * np.interp(self.df['R'],
one_freq_saline_real_list[::-1],
conductivity_list[
::-1]) # interp要求x轴为递增序列,因此此处倒序输入
def get_df(self):
return self.df
def save_20230213NO1_conductivity(path):
snsdata = SNSData(pandas_dir=path)
df = snsdata.get_df()
# 选择特定类型
filtered_df = df[~df['name'].isin(['air'])]
rslt_df = filtered_df[filtered_df['property'].str.contains('A|B|C|D|E|F|G|H') & filtered_df['name'].str.contains(
'saline|normal|tumor|peritumor')]
wb = Workbook()
ws = wb.active
for r in dataframe_to_rows(rslt_df, index=True, header=True):
ws.append(r)
wb.save('2023_2_13No1_data1.csv')
return None
# snsdata = SNSData()
# snsdata.save_20230213NO1_conductivity()
def calculate_conductivity(path):
df = pd.read_csv('2023_2_13No1_data1.csv')
index = [1, 2, 3, 7, 11, 17, 23, 31, 43, 61, 89, 127, 179, 251, 349]
my_df = []
for i in range(len(index)):
the_df = df[(df['name'] == 'tumor') & (df['property'] == 'A|B|C|D|E|F|G|H') & (df['frequency'] == index[i]) & (
df['conductivity'] > 0)]
my_df.append(the_df)
result = []
for item in my_df:
result.append((sum(item['conductivity'])) / (item.shape[0]))
df_result = pd.DataFrame({'result': result})
df_result.to_csv('2023_2_13No1_data2.csv', index=False)
return None
snsdata = SNSData(pandas_dir='./2023_2_13No1/2023_2_13_12.csv') # jiu'zhe'yi'ge'wen'ti'dui'ba
save_20230213NO1_conductivity('./2023_2_13No1/2023_2_13_12.csv')
calculate_conductivity('./2023_2_13No1/2023_2_13_12.csv')
'''
**conductivity计算为0的解决方法**
电导率计算结果为0可能是由以下几个原因导致的:
1. **数据问题:**
* 检查原始数据中是否存在异常值或缺失值,特别是在盐水电导率和测量值(magnitude, phase)列中。
* 确保盐水的浓度与电导率列表一一对应,并且浓度单位一致。
* 验证频率列表是否与数据中的频率值匹配。
2. **代码逻辑:**
* 检查筛选条件是否正确,例如`saline_concentration`的定义和筛选条件`df['name'].isin([saline_concentration])`。
* 确认`np.interp`函数的使用方式是否正确,特别是输入数据的顺序。
* 调试代码并打印中间结果,例如`one_freq_saline_real_list`和`filted_df['R']`,以检查每一步的计算结果是否符合预期。
3. **算法局限性:**
* 当前算法使用线性插值方法计算电导率,如果实际关系非线性,可能会导致误差。可以考虑使用更复杂的插值方法或拟合函数来提高精度。
**解决步骤:**
1. 首先,仔细检查数据,确保其准确性和完整性。
2. 其次,使用打印语句或调试器逐步执行代码,检查每个变量的值和计算结果。
3. 如果问题仍然存在,请尝试使用模拟数据或简化代码逻辑来定位问题。
4. 最后,考虑改进算法或使用更强大的数据分析工具来解决问题。
'''
原文地址: http://www.cveoy.top/t/topic/jupQ 著作权归作者所有。请勿转载和采集!