Pandas: 应用滚动函数计算新的列值
Pandas: Apply rolling function to compute new column value
我正在尝试通过检查前 9 行和 X 列的当前行值来计算每一行的新列 Y。基本上,每一行的新列 Y 值将告诉我们 X 列值的百分比包括当前记录在内的前 10 条记录都大于 1。下面是我正在使用的代码,但得到的结果与预期不同
[编辑]
def count_pcnt(x):
return ((np.sum(x > 1) / len(x)) * 100.0)
def run():
df = pd.DataFrame(
data={'X': ['8.12', '7.13', '-5.30', '3.21', '4.21', '3.14','8.65',
'7.33', '-5.10', '3.01']
})
df['Y'] = df['X'].rolling(window=10, min_periods=1).apply(lambda x:
count_pcnt(x)).apply(int)
预期结果[已编辑]
X Y(%)
0 8.12 100
1 7.13 100
2 -5.30 66.67
3 3.21 75
4 4.21 80
5 3.14 83.33
6 8.65 85.71
7 7.33 87.50
8 -5.10 77.77
9 3.01 80
实际
X Y
0 8.12 100
1 7.13 100
2 -5.30 0
3 3.21 0
4 4.21 0
5 3.14 0
6 8.65 0
7 7.33 0
8 -5.10 0
9 3.01 0
UPDATE 我使用了下面推荐的这个选项并且有效。虽然还有其他选择,但我觉得这样更干净
df['Y'] = df['X'].astype(float)
.rolling(window=w, min_periods=1)
.apply(lambda x: (x>1).mean()) * 100
如果你想根据接下来的 10 行而不是前面的 10 行来计算列值 - 下面是解决方案(感谢 jezrael 提供的)
df['Y'] = (df['X'].astype(float).iloc[::-1].rolling(window=10, min_periods=1).apply(lambda x: (x>1).mean()) * 100)[::-1]
您可以在 df.rolling
中设置 min_periods=1
属性:
In [927]: def count_pcnt(x):
...: return ((np.sum(x > 1) / len(x)) * 100.0)
...:
In [930]: df['Y'] = df['X'].astype(np.float64).rolling(window=10, min_periods=1).apply(lambda x: count_pcnt(x))
In [931]: df
Out[931]:
X Y
0 8.12 100.000000
1 7.13 100.000000
2 -5.30 66.666667
3 3.21 75.000000
4 4.21 80.000000
5 3.14 83.333333
6 8.65 85.714286
7 7.33 87.500000
8 -5.10 77.777778
9 3.01 80.000000
我修改了您的 count_pcnt
函数以考虑传递的变量 window 大小。我相信这就是您要找的。
您的 X 数据类型似乎是对象而不是浮点数。尝试以下操作,看看它是否有效。
df['Y'] = (
df.assign(X2=(df.X.astype(float)>0)).X2.rolling(window=10,min_periods=1)
.apply(lambda x: sum(x)*100.0/len(x))
)
df
Out[92]:
X Y
0 8.12 100.000000
1 7.13 100.000000
2 -5.30 66.666667
3 3.21 75.000000
4 4.21 80.000000
5 3.14 83.333333
6 8.65 85.714286
7 7.33 87.500000
8 -5.10 77.777778
9 3.01 80.000000
您可以使用:
- 首先通过
astype
将列 X
转换为 float
- 将参数
min_periods
添加到Series.rolling
- 相反,自定义函数将 lambda 与
(x>1).mean()
一起使用,输出相同
df = pd.DataFrame(
data={'X': ['8.12', '7.13', '-5.30', '3.21', '4.21', '3.14','8.65',
'7.33', '-5.10', '3.01']
})
w = 10
df['Y'] = df['X'].astype(float)
.rolling(window=w, min_periods=1)
.apply(lambda x: (x>1).mean()) * 100
print(df)
X Y
0 8.12 100.000000
1 7.13 100.000000
2 -5.30 66.666667
3 3.21 75.000000
4 4.21 80.000000
5 3.14 83.333333
6 8.65 85.714286
7 7.33 87.500000
8 -5.10 77.777778
9 3.01 80.000000
自定义函数的解决方案:
def count_pcnt(x):
return ((np.sum(x>1))/ len(x))*100.0
w = 10
df['Y'] = df['X'].astype(float).rolling(window=w, min_periods=1).apply(count_pcnt)
print(df)
X Y
0 8.12 100.000000
1 7.13 100.000000
2 -5.30 66.666667
3 3.21 75.000000
4 4.21 80.000000
5 3.14 83.333333
6 8.65 85.714286
7 7.33 87.500000
8 -5.10 77.777778
9 3.01 80.000000
编辑:
可以通过以下方式更改函数:
def count_pcnt(x):
return ((x>1).sum() / len(x))*100.0
或:
def count_pcnt(x):
return (x>1).mean()*100.0
我正在尝试通过检查前 9 行和 X 列的当前行值来计算每一行的新列 Y。基本上,每一行的新列 Y 值将告诉我们 X 列值的百分比包括当前记录在内的前 10 条记录都大于 1。下面是我正在使用的代码,但得到的结果与预期不同
[编辑]
def count_pcnt(x):
return ((np.sum(x > 1) / len(x)) * 100.0)
def run():
df = pd.DataFrame(
data={'X': ['8.12', '7.13', '-5.30', '3.21', '4.21', '3.14','8.65',
'7.33', '-5.10', '3.01']
})
df['Y'] = df['X'].rolling(window=10, min_periods=1).apply(lambda x:
count_pcnt(x)).apply(int)
预期结果[已编辑]
X Y(%)
0 8.12 100
1 7.13 100
2 -5.30 66.67
3 3.21 75
4 4.21 80
5 3.14 83.33
6 8.65 85.71
7 7.33 87.50
8 -5.10 77.77
9 3.01 80
实际
X Y
0 8.12 100
1 7.13 100
2 -5.30 0
3 3.21 0
4 4.21 0
5 3.14 0
6 8.65 0
7 7.33 0
8 -5.10 0
9 3.01 0
UPDATE 我使用了下面推荐的这个选项并且有效。虽然还有其他选择,但我觉得这样更干净
df['Y'] = df['X'].astype(float)
.rolling(window=w, min_periods=1)
.apply(lambda x: (x>1).mean()) * 100
如果你想根据接下来的 10 行而不是前面的 10 行来计算列值 - 下面是解决方案(感谢 jezrael 提供的)
df['Y'] = (df['X'].astype(float).iloc[::-1].rolling(window=10, min_periods=1).apply(lambda x: (x>1).mean()) * 100)[::-1]
您可以在 df.rolling
中设置 min_periods=1
属性:
In [927]: def count_pcnt(x):
...: return ((np.sum(x > 1) / len(x)) * 100.0)
...:
In [930]: df['Y'] = df['X'].astype(np.float64).rolling(window=10, min_periods=1).apply(lambda x: count_pcnt(x))
In [931]: df
Out[931]:
X Y
0 8.12 100.000000
1 7.13 100.000000
2 -5.30 66.666667
3 3.21 75.000000
4 4.21 80.000000
5 3.14 83.333333
6 8.65 85.714286
7 7.33 87.500000
8 -5.10 77.777778
9 3.01 80.000000
我修改了您的 count_pcnt
函数以考虑传递的变量 window 大小。我相信这就是您要找的。
您的 X 数据类型似乎是对象而不是浮点数。尝试以下操作,看看它是否有效。
df['Y'] = (
df.assign(X2=(df.X.astype(float)>0)).X2.rolling(window=10,min_periods=1)
.apply(lambda x: sum(x)*100.0/len(x))
)
df
Out[92]:
X Y
0 8.12 100.000000
1 7.13 100.000000
2 -5.30 66.666667
3 3.21 75.000000
4 4.21 80.000000
5 3.14 83.333333
6 8.65 85.714286
7 7.33 87.500000
8 -5.10 77.777778
9 3.01 80.000000
您可以使用:
- 首先通过
astype
将列 - 将参数
min_periods
添加到Series.rolling
- 相反,自定义函数将 lambda 与
(x>1).mean()
一起使用,输出相同
X
转换为 float
df = pd.DataFrame(
data={'X': ['8.12', '7.13', '-5.30', '3.21', '4.21', '3.14','8.65',
'7.33', '-5.10', '3.01']
})
w = 10
df['Y'] = df['X'].astype(float)
.rolling(window=w, min_periods=1)
.apply(lambda x: (x>1).mean()) * 100
print(df)
X Y
0 8.12 100.000000
1 7.13 100.000000
2 -5.30 66.666667
3 3.21 75.000000
4 4.21 80.000000
5 3.14 83.333333
6 8.65 85.714286
7 7.33 87.500000
8 -5.10 77.777778
9 3.01 80.000000
自定义函数的解决方案:
def count_pcnt(x):
return ((np.sum(x>1))/ len(x))*100.0
w = 10
df['Y'] = df['X'].astype(float).rolling(window=w, min_periods=1).apply(count_pcnt)
print(df)
X Y
0 8.12 100.000000
1 7.13 100.000000
2 -5.30 66.666667
3 3.21 75.000000
4 4.21 80.000000
5 3.14 83.333333
6 8.65 85.714286
7 7.33 87.500000
8 -5.10 77.777778
9 3.01 80.000000
编辑:
可以通过以下方式更改函数:
def count_pcnt(x):
return ((x>1).sum() / len(x))*100.0
或:
def count_pcnt(x):
return (x>1).mean()*100.0