我有一个这样的表,其中包含成千上万的clm_id:这里给出了两个clm_id。 clm-id和tmstp的顺序不限。在这里,我以升序显示了tmstp进行解释。如果cd1为50/600且cd2!= 0,则我必须创建一个指标1,否则每个clm_id的指标为0。但是对于同一个clm_id,如果cd1多次出现,那么我必须在tmstp上查看哪个是最新的,以及它们的组合是什么。就像对于clm_id = 1 cd1 = 50&cd2 = 10设置指标= 1一样。在第二行中cd1 = 600&cd2 = 10向下也设置了指标= 1,但在第三行cd1 = 600&cd2 = 0设置了指标=0。但是第一条件cd1 = 50&cd2 = 10仍然具有指标= 1,因此该clm_id指示器= 1仍然有效。但是对于clm_id = 2,由于先前的cd1 = 50和cd2 = 10设置了指示符1,但后来的cd2 = 0,所以指示符= 0,因此指示符变为0。这很复杂,因此需要您的帮助。
clm_id cd1 cd2 tmstp
1 50 . 10 2019-01-01
1 . 600 .10 . 2010-01-01
1 . 600 .0 2010-01-02
2 . 50 10 2010-01-01
2 . 50 . 0 . 2010-01-02
2 . 42 . 40 . 2010-01-02
最终结果中,每个clm_id的指示器应显示如下:
clm_id indicator
1 . 1
2 . 0
最初,我不知道对于相同的clm_id cd1和cd2组合会随时间(tmstp)改变,因此我尝试过设置指示器:
def add_inj_id(x):
if (x['cd1'] == 50 or x['cd1'] == 600) and x['cd2'] != '0':
val = 1
else:
val = 0
return val
inj_df['inj_id'] = inj_df.apply(add_inj_id, axis=1)
答案 0 :(得分:0)
如果需要,将转换 'tmstp'
转换为DateTime,以便进行比较:
df['tmstp'] = pd.to_datetime(df['tmstp'])
按'clm_id'
将数据框分组:
gb = df.groupby('clm_id')
保留结果的namedtuple列表
import collections
results = []
Result = collections.namedtuple('Result',['clm_id','indicator'])
遍历'clm_id'
组;对于每个clm_id
除以'cd1'
;查找最近的cd1
并确定其cd2
是否不为零;检查50
或600
子组是否为True;存储结果。
for clm_id,group in gb:
cd1_grp = group.groupby('cd1')
# Start with the indicators set to False
ind = {50:False,600:False}
for cd1,subgroup in cd1_grp:
if cd1 not in (50,600):
continue
most_recent = subgroup.loc[subgroup['tmstp'].idxmax()]
ind[cd1] = most_recent.cd2 != 0
indicator = (ind[50] or ind[600]) * 1
results.append(Result(clm_id,indicator))
>>> results
[Result(clm_id=1, indicator=1), Result(clm_id=2, indicator=0)]
>>> pd.DataFrame(results)
clm_id indicator
0 1 1
1 2 0
>>>
我使用嵌套的for循环(双重groupby)来计算逻辑。这是一个更好的版本-分为两列。
gb1 = df.groupby(['clm_id','cd1'])
d = {}
for (clm_id,cd1),group in gb1:
if clm_id not in d:
d[clm_id]=0
if cd1 not in (50,600):
continue
most_recent = group.loc[group['tmstp'].idxmax()]
d[clm_id] = d[clm_id] or int(most_recent.cd2 != 0)
>>> d
{1: 1, 2: 0}
>>> pd.DataFrame(list(d.items()),columns=['clm_id','indicator'])
clm_id indicator
0 1 1
1 2 0
>>>
可以用d = dict.fromkeys(df['clm_id'].unique(),0)
来创建字典。这将使if clm_id not in d:...
条件语句变得不必要。尚不清楚这将如何影响性能。
测试DataFrame
import io
s = '''clm_id cd1 cd2 tmstp
1 50 10 2019-01-01
1 600 10 2010-01-01
1 600 0 2010-01-02
2 50 10 2010-01-01
2 50 0 2010-01-02
2 42 40 2010-01-02'''
df = pd.read_csv(io.StringIO(s), delimiter='\s+')