groupby('subject')
并agg(set)
在trial
.join
两个数据框
- 创建一个使用
set
,因为目标是删除所有以前的试验。trail_n
range(x + 1)
- 取两者
difference
中的一个sets
- 如果需要,
将结果转换回 a
list
and 。explode
import pandas as pd
# data
df1 = pd.DataFrame({'subject': [1,1,1,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3],
'trial': [1,4,8,1,2,6,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,2,3,4,5,8,9,10]})
df2 = pd.DataFrame({'subject': [2, 3],
'trial': [12, 4]})
# set subject as the index in df2
df2.set_index('subject', inplace=True)
# for df1 groupby subject and agg set onto trial
df1g = pd.DataFrame(df1.groupby('subject')['trial'].agg(set))
| subject | trial |
|----------:|:---------------------------------------------------------------------|
| 1 | {8, 1, 4} |
| 2 | {1, 2, 6, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24} |
| 3 | {2, 3, 4, 5, 8, 9, 10} |
# join the dataframes
df_join = df1g.join(df2, rsuffix='_n')
| subject | trial | trial_n |
|----------:|:---------------------------------------------------------------------|----------:|
| 1 | {8, 1, 4} | nan |
| 2 | {1, 2, 6, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24} | 12 |
| 3 | {2, 3, 4, 5, 8, 9, 10} | 4 |
# this is required because set & range don't work with nan
df_join.trial_n.fillna(0, inplace=True)
# convert trial_n to a set; int is required because range doesn't work with float
df_join.trial_n = df_join.trial_n.apply(lambda x: set(range(int(x)+1)))
# take the set difference
df_join['remains'] = df_join.trial - df_join.trial_n
| subject | trial | trial_n | remains |
|----------:|:---------------------------------------------------------------------|:-------------------------------------------|:-------------------------------------------------|
| 1 | {8, 1, 4} | {0} | {8, 1, 4} |
| 2 | {1, 2, 6, 9, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24} | {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} | {13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24} |
| 3 | {2, 3, 4, 5, 8, 9, 10} | {0, 1, 2, 3, 4} | {8, 9, 10, 5} |
# create df_final & convert remains back to a list so explode can be used
df_final = pd.DataFrame(df_join.remains.map(list).map(sorted))
| subject | remains |
|----------:|:-------------------------------------------------|
| 1 | [1, 4, 8] |
| 2 | [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24] |
| 3 | [5, 8, 9, 10] |
# explode the lists
df_final = df_final.explode('remains')
| subject | remains |
|----------:|----------:|
| 1 | 1 |
| 1 | 4 |
| 1 | 8 |
| 2 | 13 |
| 2 | 14 |
| 2 | 15 |
| 2 | 16 |
| 2 | 17 |
| 2 | 18 |
| 2 | 19 |
| 2 | 20 |
| 2 | 21 |
| 2 | 22 |
| 2 | 23 |
| 2 | 24 |
| 3 | 5 |
| 3 | 8 |
| 3 | 9 |
| 3 | 10 |