python pandas 在列块上使用逻辑运算符
我有一个数据集,已经加载到一个叫做 pandas 的数据框里,内容大致如下:
n=2
np.random.seed(1)
dt = pd.DataFrame((np.random.rand(5, 2*n+1)*1000).round(), columns=['id', 'x_0', 'y_0', 'x_1', 'y_1'])
>>> dt
id x_0 y_0 x_1 y_1
0 417 720 0 302 147
1 92 186 346 397 539
2 419 685 204 878 27
3 670 417 559 140 198
4 801 968 313 692 876
[5 rows x 5 columns]
我知道这个方法只适用于 n=2 的情况,但现在我还不知道如何为其他 n 值构建列名(不过我想这可能是另一个话题的问题)。
一般来说,我可以有 n 组 x 和 y 列(这些是按月的数据)。
我需要做的是检查在同一个月里,x_i 和 y_i 的值是否都超过了某个特定的数值,如果在任何一个 n 个月里都超过了,就返回 1,否则返回 0。
所以,我正在尝试:
>>> (dt[range(1, 2*n+1, 2)] > 400)
x_0 x_1
0 True False
1 False False
2 True True
3 True False
4 True True
[5 rows x 2 columns]
>>> (dt[range(2, 2*n+1, 2)] > 300)
y_0 y_1
0 False False
1 True True
2 False False
3 True False
4 True True
[5 rows x 2 columns]
在这里,我想检查 x_i
的值是否超过 400
,以及 y_i
是否超过 300
。这样会产生两个包含 x 和 y 值的数据框(宽度为 n
列),这没问题。但是当我尝试:
(dt[range(1, 2*n+1, 2)] > 400) & (dt[range(2, 2*n+1, 2)] > 300)
它并没有逐个元素应用 & 操作符,而是返回了一个包含 NaN 的 2*n 数据框:
x_0 x_1 y_0 y_1
0 NaN NaN NaN NaN
1 NaN NaN NaN NaN
2 NaN NaN NaN NaN
3 NaN NaN NaN NaN
4 NaN NaN NaN NaN
我显然在这里漏掉了什么。我的问题是,这背后的逻辑是什么,以及如何让它正常工作。
如果我能让这个工作,我会尝试使用 any()
函数和 apply()
方法。
任何建议都很受欢迎。
*编辑 这里还有一个 R 语言的代码片段,可以解决这个问题。也许 R 的方法让我在 Python 代码上感到“负担”。
> n=2
> dt <- data.frame(id = c(417, 92, 419, 670, 801),
+ x_0 = c(720, 186, 685, 417, 968),
+ y_0 = c(0, 346, 204, 559, 313),
+ x_1 = c(302, 397, 878, 140, 692),
+ y_1 = c(147, 539, 27, 198, 876))
> (x <- (dt[,seq(2, 2*n+1, by=2)] > 400) & (dt[,seq(3, 2*n+1, by=2)] > 300))
x_0 x_1
[1,] FALSE FALSE
[2,] FALSE FALSE
[3,] FALSE FALSE
[4,] TRUE FALSE
[5,] TRUE TRUE
> (result <- apply(x, 1, any, na.rm=T))
[1] FALSE FALSE FALSE TRUE TRUE
1 个回答
0
这个方法是通过列名来进行索引的,而不是在列上使用逻辑运算符。它是通过一个叫做apply的函数来逐行处理数据的:
n=2
import numpy as np
import pandas as pd
dt = pd.DataFrame((np.random.rand(5, 2*n+1)*1000).round(), columns=['id', 'x_0', 'y_0', 'x_1', 'y_1'])
print dt
def check_x(x):
value=0
columns_with_x = [col for col in x.index if 'x_' in col]
columns_with_y = [col for col in x.index if 'y_' in col]
for each_col_x in columns_with_x:
if x[each_col_x] > 400:
for each_col_y in columns_with_y:
if x[each_col_y] > 300:
value=1
return value
checked = dt.apply(check_x, axis=1)
print checked
输出结果:
id x_0 y_0 x_1 y_1
0 251 525 976 743 206
1 324 354 238 413 93
2 21 999 731 416 431
3 652 926 131 510 627
4 124 387 747 972 678
0 1
1 0
2 1
3 1
4 1
dtype: int64