首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >检查大熊猫条件行选择中数据部分的长度

检查大熊猫条件行选择中数据部分的长度
EN

Stack Overflow用户
提问于 2022-07-15 13:42:44
回答 3查看 103关注 0票数 2

假设我有这样一只熊猫:

代码语言:javascript
运行
复制
    first   second  third
1     2       2       1
2     2       1       0
3     3       4       5
4     4       6       3
5     5       4       3
6     8       8       4
7     3       4       2
8     5       6       6

并且可以使用以下代码创建:

代码语言:javascript
运行
复制
dataframe = pd.DataFrame(
    {
        'first': [2, 2, 3, 4, 5, 8, 3, 5], 
        'second': [2, 1, 4, 6, 4, 8, 4, 6], 
        'third': [1, 0, 5, 3, 3, 4, 2, 6]
    }
)

我希望选择第二列的值大于第一列的值的行,同时,对于k连续行,第三列中的值小于第二列中的值,其中这些k连续行的最后一行正好在第二列的值大于第一列的值的行之前,而k可以是介于2到4之间的任何整数(封闭间隔)。

因此,输出应该是行:3, 7, 8

为了获得上述结果,在熊猫中使用条件行选择,我知道我应该编写如下代码:

代码语言:javascript
运行
复制
dataframe[(dataframe['first'] < dataframe['second']) & (second_condition)].index

但是我不知道该为second_condition写什么,我前面已经解释过了。有人能帮我吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-07-15 14:14:34

这里的诀窍是在布尔掩码上计算rolling sum,以找出k前几行中的值,其中third列小于second列。

代码语言:javascript
运行
复制
k = 2
m1 = df['second'].gt(df['first'])
m2 = df['third'].lt(df['second']).shift(fill_value=0).rolling(k).sum().eq(k)

代码语言:javascript
运行
复制
print(df[m1 & m2])

   first  second  third
3      3       4      5
7      3       4      2
8      5       6      6
票数 3
EN

Stack Overflow用户

发布于 2022-07-15 14:11:33

我将把我的答案集中在你问题的第二部分。您需要使用shift函数进行比较。它允许您移动行。

假设您的k固定在2,您应该这样做:

代码语言:javascript
运行
复制
import pandas as pd

df = pd.DataFrame(
    {
        'first': [2, 2, 3, 4, 5, 8, 3, 5], 
        'second': [2, 1, 4, 6, 4, 8, 4, 6], 
        'third': [1, 0, 5, 3, 3, 4, 2, 6]
    }
)

# this is the line
df[(df['third'] < df['second'].shift(1)) & (df['third'] < df['second'].shift(2))]

到底怎么回事?

通过移动一行,开始将'third'与以前的'second'值进行比较,然后在第二个条件下将其移到两个位置。

注意,这只适用于k的固定值。如果k是可变的呢?

在这种情况下,您需要动态地编写条件。下面的代码假设,对于1,k中的n 的所有值,必须满足的条件。

代码语言:javascript
运行
复制
k = 2  # pick any k > 1

df[~pd.concat([df['third'] < df['second'].shift(n) for n in range(1, k+1)]).any(level=0)].index

这是怎么回事?:长话短说

首先,我们使用shift技巧进行检查,这是对1,k中的每一个n值都符合条件的行。

代码语言:javascript
运行
复制
In [1]: [df['third'] < df['second'].shift(n) for n in range(1, k+1)]
out[1]: 
[0    False
 1     True
 2    False
 3     True
 4     True
 5    False
 6     True
 7    False
 dtype: bool,
 0    False
 1    False
 2    False
 3    False
 4     True
 5     True
 6     True
 7     True
 dtype: bool]

然后,我们将它们连接起来,创建一个单一的dataframe,并为每个k值设置一个列。

代码语言:javascript
运行
复制
In [2]: pd.concat([df['third'] < df['second'].shift(n) for n in range(1, k+1)])
Out[2]: 
0    False
1     True
2    False
3     True
4     True
5    False
6     True
7    False
0    False
1    False
2    False
3    False
4     True
5     True
6     True
7     True
dtype: bool

最后,我们选择使用符合任何列(即n的值)标准的所有行作为索引。因此:如果对任何n都是正确的,我们将返回它:

代码语言:javascript
运行
复制
In [3]: pd.concat([df['third'] < df['second'].shift(n) for n in range(1, k+1)]).any(level=0)
Out[3]: 
0    False
1     True
2    False
3     True
4     True
5     True
6     True
7     True
dtype: bool

然后,您所需要做的就是对原始数据进行投影并获取索引。

代码语言:javascript
运行
复制
In [3]: df[~pd.concat([df['third'] < df['second'].shift(n) for n in range(1, k+1)]).any(level=0)].index
Out[3]: Int64Index([0, 2], dtype='int64')

最后注

如果必须满足所有值n in 1,k的条件,则将.any替换为.all

票数 1
EN

Stack Overflow用户

发布于 2022-07-15 14:53:52

代码语言:javascript
运行
复制
# First condition is easy
cond1 = df["second"] > df["first"]

# Since the second condition compare the second and third column, let's compute
# the result before hand for convenience
s = df["third"] < df["second"]

# Now we are gonna run a rolling window over `s`. What we want is that the
# previous `k` rows of `s` are all True.
# A rolling window always ends on the current row but you want it to end on the
# previous row. So we will increase the window size by 1 and exclude the last
# element from comparison.
all_true = lambda arr: arr[:-1].all()

cond2_with_k_equal_2 = s.rolling(3).apply(all_true, raw=True)
cond2_with_k_equal_3 = s.rolling(4).apply(all_true, raw=True)
cond2_with_k_equal_4 = s.rolling(5).apply(all_true, raw=True)
cond2 = cond2_with_k_equal_2 | cond2_with_k_equal_3 | cond2_with_k_equal_4

# Or you can consolidate them into a loop
cond2 = pd.Series(False, df.index)
for k in range(2,5):
    cond2 |= s.rolling(k+1).apply(all_true, raw=True)

# Get the result
df[cond1 & cond2]
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72994967

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档