从满足数据框 Python 条件的列表中索引并保存最后 N 个点

Posted

技术标签:

【中文标题】从满足数据框 Python 条件的列表中索引并保存最后 N 个点【英文标题】:Index and save last N points from a list that meets conditions from dataframe Python 【发布时间】:2021-06-05 20:47:17 【问题描述】:

我有一个包含气体浓度和相应阀门编号的 DataFrame。这些数据是连续采集的,我们来回切换阀门(阀门 = 1 或 2)一段时间,以获得每个阀门值的 10 个循环(总共 20 个循环)。数据的 sn-p 看起来像这样(我有 2,000 多个点,每个阀门每个循环保持大约 90 秒):

gas1          valveW   time
246.9438     2       1
247.5367     2       2
246.7167     2       3
246.6770     2       4
245.9197     1       5
245.9518     1       6
246.9207     1       7
246.1517     1       8
246.9015     1       9
246.3712     2       10
247.0826     2       11
...          ...     ...

我的目标是保存每个阀门循环的最后 N 个点。例如,在阀门=1 的第一个循环中,我想在阀门切换到 2 之前索引并保存最后 N 个点。然后我会保存最后 N 个点并对它们进行平均以找到一个值来表示第一个循环。然后我想再次在valve=1时重复此步骤进行第二个循环。

我目前正在从 Matlab 转换为 Python,所以这是我要翻译的 Matlab 代码:

% NOAA high
n2o_noaaHigh = [];
co2_noaaHigh = [];
co_noaaHigh = [];
h2o_noaaHigh = [];
ind_noaaHigh_end = zeros(1,length(t_c));

numPoints = 40;
for i = 1:length(valveW_c)-1
    if (valveW_c(i) == 1 && valveW_c(i+1) ~= 1)
        test = (i-numPoints):i;
        ind_noaaHigh_end(test) = 1;
        n2o_noaaHigh = [n2o_noaaHigh mean(n2o_c(test))];
        co2_noaaHigh = [co2_noaaHigh mean(co2_c(test))];
        co_noaaHigh = [co_noaaHigh mean(co_c(test))];
        h2o_noaaHigh = [h2o_noaaHigh mean(h2o_c(test))];
    end 
end
ind_noaaHigh_end  = logical(ind_noaaHigh_end);

这是我目前对 Python 的了解:

# NOAA high
n2o_noaaHigh = [];
co2_noaaHigh = [];
co_noaaHigh = [];
h2o_noaaHigh = [];
t_c_High = []; # time

for i in range(len(valveW_c)):
    # NOAA HIGH
    if (valveW_c[i] == 1):
        t_c_High.append(t_c[i])
        n2o_noaaHigh.append(n2o_c[i])
        co2_noaaHigh.append(co2_c[i])
        co_noaaHigh.append(co_c[i])
        h2o_noaaHigh.append(h2o_c[i])

提前致谢!

【问题讨论】:

【参考方案1】:

如果您的数据框按时间排序,您可以像这样获得每个阀门的最后 N 条记录。

N=2
valve1 = df[df['valveW']==1].iloc[-N:,:]
valve2 = df[df['valveW']==2].iloc[-N:,:]

如果当前没有排序,您可以轻松地像这样对其进行排序。

df.sort_values(by=['time'])

【讨论】:

【参考方案2】:

我不确定我是否理解正确,但我想这就是你要找的:

# First we create a column to show cycles:
df['cycle'] = (df.valveW.diff() != 0).cumsum()
print(df)

    gas1    valveW  time    cycle
0   246.9438    2   1   1
1   247.5367    2   2   1
2   246.7167    2   3   1
3   246.677     2   4   1
4   245.9197    1   5   2
5   245.9518    1   6   2
6   246.9207    1   7   2
7   246.1517    1   8   2
8   246.9015    1   9   2
9   246.3712    2   10  3
10  247.0826    2   11  3

现在您可以使用groupby 方法获取每个周期最后n 个点的平均值:

n = 3 #we assume this is n
df.groupby('cycle').apply(lambda x: x.iloc[-n:, 0].mean())

输出:

cycle   0
1   246.9768
2   246.6579
3   246.7269

【讨论】:

我认为您可能想使用.iloc 而不是loc。我相信当前代码返回所有行的平均值(相当于df.groupby('cycle').mean()【参考方案3】:

让我们调用你的 DataFrame df;那么你可以这样做:

results = 

for k, v in df.groupby((df['valveW'].shift() != df['valveW']).cumsum()):
    
    results[k] = v
    print(f'[group k]')
    print(v)

Shift(),正如它所暗示的,移动阀门循环的列允许检测数字序列的变化。然后,cumsum() 有助于为具有相同编号顺序的每个组分配一个唯一编号。然后我们可以在这个专栏上做一个groupby()(这在以前是不可能的,因为组不是一个就是两个!)。

给出例如为您的代码 sn-p(保存在results):

[group 1]
       gas1  valveW  time
0  246.9438       2     1
1  247.5367       2     2
2  246.7167       2     3
3  246.6770       2     4
[group 2]
       gas1  valveW  time
4  245.9197       1     5
5  245.9518       1     6
6  246.9207       1     7
7  246.1517       1     8
8  246.9015       1     9
[group 3]
       gas1   valveW  time
9   246.3712       2    10
10  247.0826       2    11

然后得到每个循环的平均值;你可以例如做:

df.groupby((df['valveW'].shift() != df['valveW']).cumsum()).mean()

它给出(再次为您的代码 sn-p):

    gas1  valveW  time
valveW                         
1       246.96855     2.0   2.5
2       246.36908     1.0   7.0
3       246.72690     2.0  10.5

你不会太在意时间的意思,但 gas1 !

然后,基于results 你可以例如做:

n = 3
mean_n_last = []

for k, v in results.items():
    
    if len(v) < n:
        mean_n_last.append(np.nan)
    else:
        mean_n_last.append(np.nanmean(v.iloc[len(v) - n:, 0]))

它为n = 3 提供[246.9768, 246.65796666666665, nan]

【讨论】:

这很有帮助!如何平均每个循环的最后 N 个元素?您的答案是整个周期的平均值。【参考方案4】:

我们可以使用中间的block 列来标识所有块。然后我们groupby 块并对最后的nth 元素进行操作。

使用您的示例数据,我们为每个12 部分创建block 列:

df['block'] = (df.valveW != df.valveW.shift()).cumsum()
gas1 valveW time block
0 246.9438 2 1 1
1 247.5367 2 2 1
2 246.7167 2 3 1
3 246.6770 2 4 1
4 245.9197 1 5 2
5 245.9518 1 6 2
6 246.9207 1 7 2
7 246.1517 1 8 2
8 246.9015 1 9 2
9 246.3712 2 10 3
10 247.0826 2 11 3

然后我们groupby那些块并取最后一个n的平均值:

n = 2
df.groupby('block').nth(list(range(-n, 0))).gas1.mean(axis=0, level=0)

结果是每个区块最后一个n的平均值:

block
1    246.69685
2    246.52660
3    246.72690
Name: gas1, dtype: float64

【讨论】:

以上是关于从满足数据框 Python 条件的列表中索引并保存最后 N 个点的主要内容,如果未能解决你的问题,请参考以下文章

Python:从每个新行从特定列表索引开始的列表创建数据框

以最快的方式从数据框 Python 中的索引创建一个新的字典列表

八皇后问题(python)

Python列表到索引数据框

在列表框/python中保存颜色更改

从 .txt 中提取以空格分隔的列并添加以保存在新数据框中