use*_*953 7 python filtering dataframe python-3.x pandas
我有一些我打算分析的皮肤温度数据(以1Hz收集).
然而,传感器并不总是与皮肤接触.因此,我有一个挑战,即在保留实际皮肤温度数据的同时去除这些非皮肤温度数据.我有大约100个要分析的文件,所以我需要自动化.
我知道已经有类似的帖子,但是我无法用它来解决我的问题.
我的数据大致如下:
df =
timeStamp Temp
2018-05-04 10:08:00 28.63
. .
. .
2018-05-04 21:00:00 31.63
Run Code Online (Sandbox Code Playgroud)
我采取的第一步是简单地应用最小阈值 - 这已经摆脱了大部分非皮肤数据.然而,我留下了急剧的跳跃,传感器被移除或连接:
为了消除这些跳跃,我正在考虑采用一种方法,我使用temp的一阶微分,然后使用另一组阈值来摆脱我不感兴趣的数据.
例如
df_diff = df.diff(60) # period of about 60 makes jumps stick out
filter_index = np.nonzero((df.Temp <-1) | (df.Temp>0.5)) # when diff is less than -1 and greater than 0.5, most likely data jumps.
Run Code Online (Sandbox Code Playgroud)
但是,我发现自己被困在这里.主要问题是:
1)我不知道如何使用此索引列表删除df中的非皮肤数据.怎么做到这一点?
更小的问题是2)我认为我仍然会在边缘附近的数据跳跃中留下一些残留的假象(例如,更严格的阈值将开始消除好的数据).是否有更好的过滤策略或者摆脱这些文物的方法?
*按照建议编辑我还计算了二阶差异,但说实话,我认为第一阶差异将允许更严格的阈值(见下文):
*编辑2:链接到样本数据
尝试下面的代码(我使用切线函数来生成数据)。我在评论中使用了疯狂物理学家的二阶差分思想。
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
df = pd.DataFrame()
df[0] = np.arange(0,10,0.005)
df[1] = np.tan(df[0])
#the following line calculates the absolute value of a second order finite
#difference (derivative)
df[2] = 0.5*(df[1].diff()+df[1].diff(periods=-1)).abs()
df.loc[df[2] < .05][1].plot() #select out regions of a high rate-of-change
df[1].plot() #plot original data
plt.show()
Run Code Online (Sandbox Code Playgroud)
以下是输出的放大图,显示了过滤后的内容。Matplotlib 从删除的数据的开头到结尾绘制一条线。
我相信您的第一个问题已经通过上面的 .loc 选择得到了解答。
第二个问题将对您的数据集进行一些实验。上面的代码仅选择出高导数数据。您还需要选择阈值来删除零等。您可以尝试在哪里进行导数选择。您还可以绘制导数的直方图,以提示您选择什么。
此外,高阶差分方程可以帮助平滑。这应该有助于去除伪影,而无需修剪切口周围。
编辑:
可以使用以下方法应用四阶有限差分:
df[2] = (df[1].diff(periods=1)-df[1].diff(periods=-1))*8/12 - \
(df[1].diff(periods=2)-df[1].diff(periods=-2))*1/12
df[2] = df[2].abs()
Run Code Online (Sandbox Code Playgroud)
有理由认为它可能会有所帮助。对于更高阶的情况,可以从以下链接计算出或导出上述系数。 有限差分系数计算器
注:上述二阶和四阶中心差分方程不是真一阶导数。必须除以间隔长度(在本例中为 0.005)才能得到实际的导数。