我有以下数据框,其中显示了我从Item1到Item 2的移动次数。例如,从A到B有一个转换,从A到C有2个转换,从C到A有1个转换
Item1 Item2 Moves
1 A B 1
2 A C 2
3 B D 3
4 C A 1
5 C B 5
6 D B 4
7 D C 1
我想计算两个项目之间的差异,因此新构建的Dataframe将是以下
Item1 Item2 Moves
1 A B 1
2 A C 1
3 B D -1
4 C B 5
5 D C 1
有没有人知道如何使用Pandas做到这一点?我想我需要在前两列上编制索引,但我在Pandas中很新,我面临很多困难。 感谢
EDIT 不能有任何重复的对。例如你不能看到两次a-> b(但你当然可以看到b-> a)
答案 0 :(得分:4)
我确信有人可以将这种情况简化为更少的行,但我已经离开了很长时间以帮助澄清正在发生的事情。简而言之,根据“Item1”在字母表中是否早于“Item2”,将数据帧拆分为两部分。然后翻转'Item1'和'Item2'并否定'Moves'为一件。将它们粘合在一起并使用groupby
函数来聚合行。
>>> df
Item1 Item2 Moves
0 A B 1
1 A C 2
2 B D 3
3 C A 1
4 C B 5
5 D B 4
6 D C 1
>>> swapidx = df['Item1'] < df['Item2']
>>> df1 = df[swapidx]
>>> df2 = df[swapidx^True]
>>> df1
Item1 Item2 Moves
0 A B 1
1 A C 2
2 B D 3
>>> df2
Item1 Item2 Moves
3 C A 1
4 C B 5
5 D B 4
6 D C 1
>>> df2[['Item1', 'Item2']] = df2[['Item2', 'Item1']]
>>> df2['Moves'] = df2['Moves']*-1
>>> df2
Item1 Item2 Moves
3 A C -1
4 B C -5
5 B D -4
6 C D -1
>>> df3 = df1.append(df2)
>>> df3.groupby(['Item1', 'Item2'], as_index=False).sum()
Item1 Item2 Moves
0 A B 1
1 A C 1
2 B C -5
3 B D -1
4 C D -1
答案 1 :(得分:1)
这是一种方法:
首先创建一个只包含Item1和Item2字符串的行。
In [11]: df['Items'] = df.apply(lambda row: row['Item1'] + row['Item2'], axis=1)
In [12]: df
Out[12]:
Item1 Item2 Moves Items
1 A B 1 AB
2 A C 2 AC
3 B D 3 BD
4 C A 1 CA
5 C B 5 CB
6 D B 4 DB
7 D C 1 DC
如果Items
在(字母顺序)中,请将其保留,否则切换它并取消Moves
:
In [13]: df[['Items','Moves']] = df.apply(lambda row: (row[['Items', 'Moves']])
if row['Items'][0] <= row['Items'][1]
else (row['Items'][::-1], -row['Moves']),
axis=1)
In [14]: df
Out[14]:
Item1 Item2 Moves Items
1 A B 1 AB
2 A C 2 AC
3 B D 3 BD
4 C A -1 AC
5 C B -5 BC
6 D B -4 BD
7 D C -1 CD
In [15]: g = df.groupby('Items')
In [16]: g.sum()
Out[16]:
Moves
Items
AB 1
AC 1
BC -5
BD -1
CD -1
大部分时间都是如此,对您来说可能已经足够了。
要获得所需的最终输出,hackey方式可能是:
In [17]: df1 = g.first() # the first row in each group
In [18]: df1.Moves = g.sum()
In [19]: df2 = df1.reset_index(drop=True)
In [20]: df2
Out[20]:
Item1 Item2 Moves
0 A B 1
1 A C 1
2 C B -5
3 B D -1
4 D C -1
然而,请注意否定是不对的(对于那些错误的方式,例如DC而不是CD):
In [21]: df2.Moves = df2.apply(lambda row: row['Moves']
if row['Item1'] <= row['Item2']
else -row['Moves'],
axis=1)
In [22]: df2
Out[22]:
Item1 Item2 Moves
0 A B 1
1 A C 1
2 C B 5
3 B D -1
4 D C 1