【发布时间】:2015-01-19 15:11:04
【问题描述】:
我正在尝试在数据框中执行以下操作。 如果 Period 不是 1,则更改列损耗值,然后将该行中保留列的值乘以 groupby 中上一行中的损耗值。我的尝试如下:
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
【问题讨论】:
-
其实,只是作为这个的后续。上面的代码工作正常,问题解决了。然后我将它调整为我更复杂的问题,我开始收到错误,现在即使上面的代码也没有运行。这是我在第 22 行遇到的错误。“引发 TypeError('插入列的不兼容索引'我的 pandas 版本是 0.15.2 我有 0.12 但读到有一些问题,所以升级到 0.15.2 但它没有解决问题。 TypeError: incompatible index of inserted column with frame index" 我还使用 Python 2.7.5 | Anaconda 1.8.0(64 位)和 Spyder 接口。