为每个ID的关联ID求布尔值之和,并将其分配给ID

2024-03-29 08:18:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个名为复合的数据框,看起来像这样:

| ID | Person.ID | V.F   | V.nF  |
|----|-----------|-------|-------|
| 1  | 111       | True  | True  |
| 2  | 222       | False | True  |
| 3  | 333       | True  | False |
| 4  | 444       | True  | False |
| 5  | 555       | True  | True  |
| 6  | 666       | False | True  |

对于每个个人ID,在一个名为nn\u list的字典中,我有所有相关的个人ID对于每个个人ID。这看起来像:

{ 111:[222,333,444],
222:[111,333],
333:[444],
444:[222,555],
555:[333,666],
666:[222],
}

我想看看字典里所有相关的单词个人ID对于给定的ID,将相关ID的布尔值(每列)相加,然后在每行的新列中指定该值。结果如下所示:

| ID | Person.ID | V.F   | V.nF  | n_V.F | n_V.nF |
|----|-----------|-------|-------|-------|--------|
| 1  | 111       | True  | True  | 2     | 1      |
| 2  | 222       | False | True  | 2     | 1      |
| 3  | 333       | True  | False | 1     | 0      |
| 4  | 444       | True  | False | 1     | 2      |
| 5  | 555       | True  | True  | 1     | 1      |
| 6  | 666       | False | True  | 0     | 1      |

我目前能够以一种非常缓慢和低效的方式完成这项工作:

l=[composite.loc[composite['Person.ID'].isin(nn_list[x]),'V.F'].sum() for x in composite['Person.ID']]
composite['n_V.F']=l

l=[composite.loc[composite['Person.ID'].isin(nn_list[x]),'V.nF'].sum() for x in composite['Person.ID']]
composite['n_V.nF']=l

有没有一个更聪明的方法来做到这一点,使它不需要很长时间运行?谢谢!你知道吗


Tags: 数据inidfalsetruefor字典nn
3条回答

将您的dict分配给d。您可以使用dict理解直接对d的值使用.locsum。之后,从结果dict构造dataframe并连接回df

df1 = df.set_index('Person.ID')
n = {k: df1.loc[v, ['V.F', 'V.nF']].values.sum(0) for k, v in d.items()}

Out[889]:
{111: array([2, 1]),
 222: array([2, 1]),
 333: array([1, 0]),
 444: array([1, 2]),
 555: array([1, 1]),
 666: array([0, 1])}

df2 = pd.DataFrame.from_dict(n, orient='index', columns=['n_V.F', 'n_V.nF'])
df1.join(df2).reset_index()

Out[898]:
   Person.ID  ID    V.F   V.nF  n_V.F  n_V.nF
0        111   1   True   True      2       1
1        222   2  False   True      2       1
2        333   3   True  False      1       0
3        444   4   True  False      1       2
4        555   5   True   True      1       1
5        666   6  False   True      0       1

我们可以做explode然后merge:注意,explode在pandas的0.25之后可用

s=pd.Series(d).explode().to_frame('Person.ID').reset_index()
s=s.merge(df).groupby('index')[['V.F','V.nF']].sum()
Newdf=pd.concat([df.set_index('Person.ID'),s.add_prefix('n_')],axis=1).reset_index()
Newdf
   index  ID    V.F   V.nF  n_V.F  n_V.nF
0    111   1   True   True    2.0     1.0
1    222   2  False   True    2.0     1.0
2    333   3   True  False    1.0     0.0
3    444   4   True  False    1.0     2.0
4    555   5   True   True    1.0     1.0
5    666   6  False   True    0.0     1.0

d={ 111:[222,333,444],
222:[111,333],
333:[444],
444:[222,555],
555:[333,666],
666:[222],
}

另一种方法是map

composite.set_index('Person.ID', inplace=True)

s = pd.concat(pd.Series(y, index=[x]*len(y)) for x,y in d.items())

composite['n_V.F'] = s.map(u['V.F']).groupby(level=0).sum()
composite['n_V.nF'] = s.map(u['V.nF']).groupby(level=0).sum()

输出:

           ID    V.F   V.nF  n_V.F  n_V.nF
Person.ID                                 
111         1   True   True    2.0     1.0
222         2  False   True    2.0     1.0
333         3   True  False    1.0     0.0
444         4   True  False    1.0     2.0
555         5   True   True    1.0     1.0
666         6  False   True    0.0     1.0

相关问题 更多 >