我有一个名为df的数据框,如下所示:(没有重复的df行)
a_id b_id
111111 18
111111 17
222222 18
333333 14
444444 13
555555 18
555555 24
222222 13
222222 17
333333 17
我希望将其反转为数据帧df_2,如下所示:
a_one a_two b_list number_of_b
222222 444444 13 1
111111 222222 17,18 2
111111 333333 17 1
111111 222222 17 1
222222 333333 17 1
111111 555555 18 1
222222 555555 18 1
如果a_id共享相同的b_id,则它们在df_2;
上成为一对df_2的b_list是相应的b_id;
number_of_b是b_list
的长度答案 0 :(得分:1)
我有一个解决方案:
首先,制作具有相同a_id
的{{1}}的组合:
b_id
from itertools import combinations
df = df.groupby("b_id").apply(lambda x: list(combinations(x["a_id"], 2))).apply(pd.Series).stack()
现在是:
df
然后拆分系列,重置索引并连接 b_id
13 0 (444444, 222222)
17 0 (111111, 222222)
1 (111111, 333333)
2 (222222, 333333)
18 0 (111111, 222222)
1 (111111, 555555)
2 (222222, 555555)
的外观:
b_id
现在我们得到:
df = df.apply(pd.Series).reset_index().groupby([0,1])["b_id"].apply(lambda x:x.values).reset_index()
这几乎就是你所需要的。 并得到确切的结果:
0 1 b_id
0 111111 222222 [17, 18]
1 111111 333333 [17]
2 111111 555555 [18]
3 222222 333333 [17]
4 222222 555555 [18]
5 444444 222222 [13]
最终结果:
df.columns = ["a_one", "a_two", "b_list"]
df["number_of_b"] = df.b_list.apply(len)
为了清晰起见,整个代码:
a_one a_two b_list number_of_b
0 111111 222222 [17, 18] 2
1 111111 333333 [17] 1
2 111111 555555 [18] 1
3 222222 333333 [17] 1
4 222222 555555 [18] 1
5 444444 222222 [13] 1
这不是那种幻想。期待更好的解决方案!
答案 1 :(得分:1)
使用带有一系列groupby和转换的链式操作:
from itertools import combinations
df2 = (
df.groupby('b_id')['a_id']
.apply(lambda x: list(combinations(x.values,2)))
.apply(pd.Series).stack()
.reset_index(0)
.groupby(0).apply(lambda x: [len(x), x.b_id.astype(str).tolist()])
.apply(pd.Series)
.rename(columns={0:'b_list', 1:'number_of_b'})
.pipe(lambda x: x.reset_index(drop=True)
.join(x.reset_index()[0].apply(pd.Series)))
.rename(columns={0:'a_one', 1:'a_two'})
.assign(number_of_b=lambda x: x.number_of_b.str.join(','))
)[['a_one','a_two','b_list','number_of_b']]
df2
Out[123]:
a_one a_two b_list number_of_b
0 111111 222222 2 17,18
1 111111 333333 1 17
2 111111 555555 1 18
3 222222 333333 1 17
4 222222 555555 1 18
5 444444 222222 1 13