gpt4 book ai didi

python - 在 python pandas 中应用带有 shift 函数的 lambda 是要替换一些空元素

转载 作者:太空宇宙 更新时间:2023-11-04 01:10:30 25 4
gpt4 key购买 nike

我正在尝试在数据框中执行以下操作。如果 Period 不为 1,则更改 Column Attrition 的值,然后将该行中保留列的值乘以 groupby 上一行中的 attrition 值。我的尝试如下:

import pandas as pd

data = {'Country': ['DE', 'DE', 'DE', 'US', 'US', 'US', 'FR', 'FR', 'FR'],
'Week': ['201426', '201426', '201426', '201426', '201425', '201425', '201426', '201426', '201426'],
'Period': [1, 2, 3, 1, 1, 2, 1, 2, 3],
'Attrition': [0.5,'' ,'' ,0.85 ,0.865,'' ,0.74 ,'','' ],
'Retention': [0.95,0.85,0.94,0.85,0.97,0.93,0.97,0.93,0.94]}

df = pd.DataFrame(data, columns= ['Country', 'Week', 'Period', 'Attrition','Retention'])
print df

给我这个输出:

  Country    Week  Period Attrition  Retention
0 DE 201426 1 0.5 0.95
1 DE 201426 2 0.85
2 DE 201426 3 0.94
3 US 201426 1 0.85 0.85
4 US 201425 1 0.865 0.97
5 US 201425 2 0.93
6 FR 201426 1 0.74 0.97
7 FR 201426 2 0.93
8 FR 201426 3 0.94

以下:

df['Attrition'] = df.groupby(['Country','Week']).apply(lambda x: x.Attrition.shift(1)*x['Retention'] if x.Period != 1 else x.Attrition)

print df

给我这个错误:

df['Attrition'] = df.groupby(['Country','Week']).apply(lambda x: x.Attrition.shift(1)*x['Retention'] if x.Period != 1 else x.Attrition)

ValueError:具有多个元素的数组的真值不明确。使用 a.any() 或 a.all()

更新:完整的编译解决方案

下面是我之后的完整工作解决方案,基本上是使用 Primer 的答案,但添加了一个 while 循环以继续在数据框列上运行 Lambda 函数,直到不再有 NaN。

import pandas as pd
import numpy as np

data = {'Country': ['DE', 'DE', 'DE', 'US', 'US', 'US', 'FR', 'FR', 'FR'],
'Week': ['201426', '201426', '201426', '201426', '201425', '201425', '201426', '201426', '201426'],
'Period': [1, 2, 3, 1, 1, 2, 1, 2, 3],
'Attrition': [0.5, '' ,'' ,0.85 ,0.865,'' ,0.74 ,'','' ],
'Retention': [0.95,0.85,0.94,0.85,0.97,0.93,0.97,0.93,0.94]}

df = pd.DataFrame(data, columns= ['Country', 'Week', 'Period', 'Attrition','Retention'])
print df

输出:开始 DF

  Country    Week  Period Attrition  Retention
0 DE 201426 1 0.5 0.95
1 DE 201426 2 0.85
2 DE 201426 3 0.94
3 US 201426 1 0.85 0.85
4 US 201425 1 0.865 0.97
5 US 201425 2 0.93
6 FR 201426 1 0.74 0.97
7 FR 201426 2 0.93
8 FR 201426 3 0.94

解决方案:

#Replaces empty string with NaNs
df['Attrition'] = df['Attrition'].replace('', np.nan)

#Stores a count of the number of null or NaNs in the column.
ContainsNaN = df['Attrition'].isnull().sum()

#run the loop while there are some NaNs in the column.
while ContainsNaN > 0:
df['Attrition'] = df.groupby(['Country','Week']).apply(lambda x: pd.Series(np.where((x.Period != 1), x.Attrition.shift() * x['Retention'], x.Attrition)))
ContainsNaN = df['Attrition'].isnull().sum()

print df

输出:结果

  Country    Week  Period Attrition  Retention
0 DE 201426 1 0.5 0.95
1 DE 201426 2 0.425 0.85
2 DE 201426 3 0.3995 0.94
3 US 201426 1 0.85 0.85
4 US 201425 1 0.865 0.97
5 US 201425 2 0.80445 0.93
6 FR 201426 1 0.74 0.97
7 FR 201426 2 0.6882 0.93
8 FR 201426 3 0.646908 0.94

最佳答案

首先,您的 Attrition 列将数字数据与空字符串 '' 混合,这通常不是一个好主意,应该在尝试对此列进行计算之前解决:

df.loc[df['Attrition'] == '', 'Attrition'] = pd.np.nan
df['Attrition'] = df.Attrition.astype('float')

你得到的错误是因为你在 .apply 中的条件:x.Period != 1 产生了一个 bool 数组:

0    False
1 True
2 True
3 False
4 False
5 True
6 False
7 True
8 True
Name: Period, dtype: bool

.apply 不知道如何处理,因为它有歧义(即在这种情况下什么应该为真?)。

您可能会考虑 numpy.where对于这个任务:

import numpy as np
g = df.groupby(['Country','Week'], as_index=0, group_keys=0)
df['Attrition'] = g.apply(lambda x: pd.Series(np.where((x.Period != 1), x.Attrition.shift() * x['Retention'], x.Attrition)).fillna(method='ffill')).values
df

产量:

  Country    Week  Period  Attrition  Retention
0 DE 201426 1 0.500 0.95
1 DE 201426 2 0.425 0.85
2 DE 201426 3 0.425 0.94
3 US 201426 1 0.740 0.85
4 US 201425 1 0.688 0.97
5 US 201425 2 0.688 0.93
6 FR 201426 1 0.865 0.97
7 FR 201426 2 0.804 0.93
8 FR 201426 3 0.850 0.94

请注意,我添加了 .fillna 方法,该方法用最后观察到的值填充 NaN

关于python - 在 python pandas 中应用带有 shift 函数的 lambda 是要替换一些空元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28027731/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com