Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/344.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/git/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 根据列前缀将DataFrame分为多个部分,并对这些部分执行算术运算_Python_Pandas_Dataframe - Fatal编程技术网

Python 根据列前缀将DataFrame分为多个部分,并对这些部分执行算术运算

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

我有一个表,其中有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   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