Python 根据列前缀将DataFrame分为多个部分,并对这些部分执行算术运算
我有一个表,其中有200多列。这些列具有不同的对(例如,两种类型的奔驰),下面是一个示例。我想做的是计算一个新列的每一对的差值(例如最后一列)。我在考虑根据第一个字母用两个表(A和B)分隔这些表,并对列进行排序。但是有没有更有效的方法来保护熊猫呢?谢谢Python 根据列前缀将DataFrame分为多个部分,并对这些部分执行算术运算,python,pandas,dataframe,Python,Pandas,Dataframe,我有一个表,其中有200多列。这些列具有不同的对(例如,两种类型的奔驰),下面是一个示例。我想做的是计算一个新列的每一对的差值(例如最后一列)。我在考虑根据第一个字母用两个表(A和B)分隔这些表,并对列进行排序。但是有没有更有效的方法来保护熊猫呢?谢谢 A_Benz B_Benz A_Audi B_Audi A_Honda B_Honda dif_Audi 1 0 1 1 0 0 0 1 0 0 1 0 0 -1 1 0 0 1
A_Benz B_Benz A_Audi B_Audi A_Honda B_Honda dif_Audi
1 0 1 1 0 0 0
1 0 0 1 0 0 -1
1 0 0 1 0 0 -1
1 0 1 1 1 1 0
1 0 0 1 0 0 -1
假设这是你的出发点-
df
A_Benz B_Benz A_Audi B_Audi A_Honda B_Honda
1 1 0 1 1 0 0
2 1 0 0 1 0 0
3 1 0 0 1 0 0
4 1 0 1 1 1 1
5 1 0 0 1 0 0
选项1这将是
过滤器的一个很好的用例:
i = df.filter(regex='^A_*')
j = df.filter(regex='^B_*')
i.columns = i.columns.str.split('_', 1).str[-1]
j.columns = j.columns.str.split('_', 1).str[-1]
(i - j).add_prefix('diff_')
diff_Benz diff_Audi diff_Honda
1 1 0 0
2 1 -1 0
3 1 -1 0
4 1 0 0
5 1 -1 0
如果要将其添加回原始数据帧,可以使用concat
df = pd.concat([df, (i - j).add_prefix('diff_')], axis=1)
选项2
使用diff
的替代方案;这会做很多不必要的减法:
import re
# if needed, order the columns correctly
df = df[sorted(df.columns, key=lambda x: x.split('_', 1)[1])]
# compute consecutive column differences
df.diff(-1, axis=1).iloc[:, ::2].rename(columns=lambda x: re.sub('A_', 'diff_', x))
diff_Benz diff_Audi diff_Honda
1 1.0 0.0 0.0
2 1.0 -1.0 0.0
3 1.0 -1.0 0.0
4 1.0 0.0 0.0
5 1.0 -1.0 0.0
更有效的方法是(类似于@jpp的方法)——
IIUC
这是一个基于numpy的解决方案
虽然性能可能不是问题,但这应该比pandonic方法更有效
df = df[sorted(df, key=lambda x: x.split('_')[::-1])]
A = df.values
cars = [x[2:] for x in df.columns[::2]]
res = df.join(pd.DataFrame(A[:, ::2] - A[:, 1::2], columns=cars).add_prefix('Diff_'))
结果
A_Audi B_Audi A_Benz B_Benz A_Honda B_Honda Diff_Audi Diff_Benz \
0 1 1 1 0 0 0 0 1
1 0 1 1 0 0 0 -1 1
2 0 1 1 0 0 0 -1 1
3 1 1 1 0 1 1 0 1
4 0 1 1 0 0 0 -1 1
Diff_Honda
0 0
1 0
2 0
3 0
4 0
解释
- 按汽车品牌对列进行排序,然后添加前缀
- 通过列表提取汽车制造
- 使用
numpy
数组切片构建差异数据帧并将其连接到原始数据帧
感谢您提供的出色解决方案。在我正在处理的情况下,名称实际上带有下划线“”,比如“A_Honda_typeS,B_Honda_typeS”。如何将字符串与第一个“”分开?B_Honda_类型,以便您希望它成为Honda或Honda_类型?@Alexu抱歉,没有明确说明。我希望列名在第一个下划线处拆分(以区分A和B)。在某些情况下,名称带有一个或多个下划线,如Honda_类型。@Alexu请尝试使用以下行s=pd.Series(df.columns).str.replace(''.','~',1).str.split('~',expand=True)[1]
不确定为什么它在我这边不起作用。我得到的只是没有任何数据的行索引。无论如何谢谢你!回答问题后,请不要编辑问题。我已经后退了。确保下次你的问题完成。或者做一些研究,然后问一个单独的问题。谢谢,谢谢!但是,我想问一下,如果列名有多个“u”,比如“A_Honda_typeS”,会怎么样?Alexu我从一开始就考虑过这一点,所以我确保代码在第一次拆分时只拆分一次。查看str.split
@AlexXu的第二个参数,还请注意,第二个方法没有这个问题,只要列按正确的顺序排序
df = df[sorted(df, key=lambda x: x.split('_')[::-1])]
A = df.values
cars = [x[2:] for x in df.columns[::2]]
res = df.join(pd.DataFrame(A[:, ::2] - A[:, 1::2], columns=cars).add_prefix('Diff_'))
A_Audi B_Audi A_Benz B_Benz A_Honda B_Honda Diff_Audi Diff_Benz \
0 1 1 1 0 0 0 0 1
1 0 1 1 0 0 0 -1 1
2 0 1 1 0 0 0 -1 1
3 1 1 1 0 1 1 0 1
4 0 1 1 0 0 0 -1 1
Diff_Honda
0 0
1 0
2 0
3 0
4 0