Python pandas:将函数应用于dataframe.rolling()

时间:2018-04-15 03:52:35

标签: python pandas rolling-computation

我有这个数据框:

In[1]df = pd.DataFrame([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25]])
In[2]df
Out[2]: 
    0   1   2   3   4
0   1   2   3   4   5
1   6   7   8   9  10
2  11  12  13  14  15
3  16  17  18  19  20
4  21  22  23  24  25

我需要实现这个目标:

  1. 对于我的数据框中的每一行,
  2. 如果任何3个连续单元格中的2个或更多值大于10,
  3. 然后应将3个单元格中的最后一个标记为True。
  4. 根据上述标准,结果数据帧df1应该是相同的大小,其中的True为False:

    In[3]df1
    Out[3]: 
        0   1      2      3      4
    0 NaN NaN  False  False  False
    1 NaN NaN  False  False  False
    2 NaN NaN   True   True   True
    3 NaN NaN   True   True   True
    4 NaN NaN   True   True   True
    
    • df1.iloc [0,1]在该单元格中是NaN bacause,只给出了两个数字,但至少需要3个数字才能进行测试。
    • df1.iloc [1,3]为假,因为[7,8,9]中没有一个大于10
    • df1.iloc [3,4]为真,因为[18,19,20]中的2或更多大于10

    我认为带有函数的dataframe.rolling.apply()可能是解决方案,但究竟是怎么回事?

3 个答案:

答案 0 :(得分:1)

在布尔数据帧上使用ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS) .tlsVersions(TlsVersion.TLS_1_2) .cipherSuites( CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA, CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA) .build(); OkHttpClient client = new OkHttpClient.Builder().connectionSpecs(Collections.singletonList(spec)).build(); Request request = new Request.Builder().url("wss://mywssdomain").build(); WebSocketListenerCP listener = new WebSocketListenerCP(); WebSocket ws = client.newWebSocket(request, listener); client.dispatcher().executorService().shutdown();

sum

您可以通过屏蔽na。

确定确切的请求输出
df.gt(10).rolling(3, axis=1).sum().ge(2)

       0      1      2      3      4
0  False  False  False  False  False
1  False  False  False  False  False
2  False  False   True   True   True
3  False  False   True   True   True
4  False  False   True   True   True

答案 1 :(得分:0)

你是对的,使用rolling()是可行的方法。但是,您必须牢记,rolling()会使用新值替换窗口末尾的值,因此您不能只使用True标记窗口,每当有False时,您也会获得df = pd.DataFrame([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25]]) 条件不适用

以下是使用示例数据框并执行所需转换的代码:

def fun(x):
    num = 0
    for i in x:
        num += 1 if i > 10 else 0
    return 1 if num >= 2 else -1

现在,定义一个以窗口作为参数并返回条件是否满足的函数

df.rolling(3, axis=1).apply(fun)

我已将阈值硬编码为10.因此,如果在任何窗口中,大于10的值的数量大于或等于2,则最后一个值将替换为1(表示为True),否则将替换为-1 (表示假)。

如果您想将阈值参数保留为变量,请查看this answer以将它们作为参数传递。

现在在滚动窗口上应用该函数,使用窗口大小为3,轴1,此外如果你不想要NaN,那么你也可以在参数中将min_periods设置为1.

  0   1    2    3    4
0 NaN NaN -1.0 -1.0 -1.0
1 NaN NaN -1.0 -1.0 -1.0
2 NaN NaN  1.0  1.0  1.0
3 NaN NaN  1.0  1.0  1.0
4 NaN NaN  1.0  1.0  1.0

将输出生成为

function copy(arr) {
  return arr
    .map(x => Object
      .keys(x)
      .reduce((acc, y) => {
        acc[y] = x[y]
        return acc
      }, {}))
}

答案 2 :(得分:0)

你需要 -

import pandas as pd
import numpy as np
df = pd.DataFrame([[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15],[16,17,18,19,20],[21,22,23,24,25]])
df1 = df.apply(lambda x: pd.Series([np.nan, np.nan]+[all(j>10 for j in i) for i in zip(x[0::1], x[1::1], x[2::1])]), axis=1)

print(df1)

<强>输出

0   1      2      3      4
0 NaN NaN  False  False  False
1 NaN NaN  False  False  False
2 NaN NaN   True   True   True
3 NaN NaN   True   True   True
4 NaN NaN   True   True   True

<强>解释

list(zip(x[0::1], x[1::1], x[2::1])

将其分解为每行占用3列 -

0             [(1, 2, 3), (2, 3, 4), (3, 4, 5)]
1            [(6, 7, 8), (7, 8, 9), (8, 9, 10)]
2    [(11, 12, 13), (12, 13, 14), (13, 14, 15)]
3    [(16, 17, 18), (17, 18, 19), (18, 19, 20)]
4    [(21, 22, 23), (22, 23, 24), (23, 24, 25)]

all(j>10 for j in i)

检查元组列表中的每个元素,如果元组中的所有元素都大于10,则输出True

连接[np.nan, np.nan]以匹配您的输出。希望有所帮助。