Pandas 计算给定多个条件的多列总和
Pandas Calculate Sum of Multiple Columns Given Multiple Conditions
我有一个宽 table 格式如下(最多 10 人):
person1_status | person2_status | person3_status | person1_type | person_2 type | person3_type
0 | 1 | 0 | 7 | 4 | 6
其中 status 可以是 0 或 1(前 3 列)。
其中 type 可以是 4-7 之间的#。这里的值对应另一个table,根据类型指定一个值。所以...
Type | Value
4 | 10
5 | 20
6 | 30
7 | 40
我需要计算两列,'A' 和 'B',其中:
- A 是每个人的类型(在该行中)的值的 sum,其中
状态 = 0。
- B 是每个人的类型(在该行中)的值的 sum,其中
状态 = 1.
例如,结果列 'A' 和 'B' 将如下所示:
A | B
70 | 10
对此的解释:
'A' 的值为 70,因为 person1 和 person3 的 "status" 为 0,对应的类型为 7 和 6(对应值 30 和 40)。
同样,应该有另一列 'B' 的值为“10”,因为只有 person2 的状态为“1”且其类型为“4”(对应值为 10)。
这可能是一个愚蠢的问题,但我如何以矢量化的方式做到这一点?我不想使用 for 循环或任何东西,因为它会降低效率...
我希望这是有道理的...有人可以帮助我吗?我想我在想办法解决这个问题时已经脑残了。
对于更简单的计算列,我只是 np.where 但我有点卡在这里,因为我需要在给定特定条件的情况下计算多个列的值的总和,同时从分开 table...
希望有意义
使用 filter 方法过滤其中出现字符串的列名称。
为查找值创建数据框other_table
并将索引设置为类型列。
df_status = df.filter(like = 'status')
df_type = df.filter(like = 'type')
df_type_lookup = df_type.applymap(lambda x: other_table.loc[x]).values
df['A'] = np.sum((df_status == 0).values * df_type_lookup, 1)
df['B'] = np.sum((df_status == 1).values * df_type_lookup, 1)
完整示例如下:
创建虚假数据
df = pd.DataFrame({'person_1_status':np.random.randint(0, 2,1000) ,
'person_2_status':np.random.randint(0, 2,1000),
'person_3_status':np.random.randint(0, 2,1000),
'person_1_type':np.random.randint(4, 8,1000),
'person_2_type':np.random.randint(4, 8,1000),
'person_3_type':np.random.randint(4, 8,1000)},
columns= ['person_1_status', 'person_2_status', 'person_3_status',
'person_1_type', 'person_2_type', 'person_3_type'])
person_1_status person_2_status person_3_status person_1_type \
0 1 0 0 7
1 0 1 0 6
2 1 0 1 7
3 0 0 0 7
4 0 0 1 4
person_3_type person_3_type
0 5 5
1 7 7
2 7 7
3 7 7
4 7 7
制作other_table
other_table = pd.Series({4:10, 5:20, 6:30, 7:40})
4 10
5 20
6 30
7 40
dtype: int64
将状态和类型列过滤到它们自己的数据框中
df_status = df.filter(like = 'status')
df_type = df.filter(like = 'type')
进行查找table
df_type_lookup = df_type.applymap(lambda x: other_table.loc[x]).values
跨行应用矩阵乘法和求和。
df['A'] = np.sum((df_status == 0).values * df_type_lookup, 1)
df['B'] = np.sum((df_status == 1).values * df_type_lookup, 1)
输出
person_1_status person_2_status person_3_status person_1_type \
0 0 0 1 7
1 0 1 0 4
2 0 1 1 7
3 0 1 0 6
4 0 0 1 5
person_2_type person_3_type A B
0 7 5 80 20
1 6 4 20 30
2 5 5 40 40
3 6 4 40 30
4 7 5 60 20
考虑数据帧df
mux = pd.MultiIndex.from_product([['status', 'type'], ['p%i' % i for i in range(1, 6)]])
data = np.concatenate([np.random.choice((0, 1), (10, 5)), np.random.rand(10, 5)], axis=1)
df = pd.DataFrame(data, columns=mux)
df
我们可以为type == 1
这样做的结构方式
df.status.mul(df.type).sum(1)
0 0.935290
1 1.252478
2 1.354461
3 1.399357
4 2.102277
5 1.589710
6 0.434147
7 2.553792
8 1.205599
9 1.022305
dtype: float64
和 type == 0
df.status.rsub(1).mul(df.type).sum(1)
0 1.867986
1 1.068045
2 0.653943
3 2.239459
4 0.214523
5 0.734449
6 1.291228
7 0.614539
8 0.849644
9 1.109086
dtype: float64
您可以使用以下代码获取此格式的列
df.columns = df.columns.str.split('_', expand=True)
df = df.swaplevel(0, 1, 1)
我有一个宽 table 格式如下(最多 10 人):
person1_status | person2_status | person3_status | person1_type | person_2 type | person3_type
0 | 1 | 0 | 7 | 4 | 6
其中 status 可以是 0 或 1(前 3 列)。
其中 type 可以是 4-7 之间的#。这里的值对应另一个table,根据类型指定一个值。所以...
Type | Value
4 | 10
5 | 20
6 | 30
7 | 40
我需要计算两列,'A' 和 'B',其中:
- A 是每个人的类型(在该行中)的值的 sum,其中 状态 = 0。
- B 是每个人的类型(在该行中)的值的 sum,其中 状态 = 1.
例如,结果列 'A' 和 'B' 将如下所示:
A | B
70 | 10
对此的解释:
'A' 的值为 70,因为 person1 和 person3 的 "status" 为 0,对应的类型为 7 和 6(对应值 30 和 40)。
同样,应该有另一列 'B' 的值为“10”,因为只有 person2 的状态为“1”且其类型为“4”(对应值为 10)。
这可能是一个愚蠢的问题,但我如何以矢量化的方式做到这一点?我不想使用 for 循环或任何东西,因为它会降低效率...
我希望这是有道理的...有人可以帮助我吗?我想我在想办法解决这个问题时已经脑残了。
对于更简单的计算列,我只是 np.where 但我有点卡在这里,因为我需要在给定特定条件的情况下计算多个列的值的总和,同时从分开 table...
希望有意义
使用 filter 方法过滤其中出现字符串的列名称。
为查找值创建数据框other_table
并将索引设置为类型列。
df_status = df.filter(like = 'status')
df_type = df.filter(like = 'type')
df_type_lookup = df_type.applymap(lambda x: other_table.loc[x]).values
df['A'] = np.sum((df_status == 0).values * df_type_lookup, 1)
df['B'] = np.sum((df_status == 1).values * df_type_lookup, 1)
完整示例如下:
创建虚假数据
df = pd.DataFrame({'person_1_status':np.random.randint(0, 2,1000) ,
'person_2_status':np.random.randint(0, 2,1000),
'person_3_status':np.random.randint(0, 2,1000),
'person_1_type':np.random.randint(4, 8,1000),
'person_2_type':np.random.randint(4, 8,1000),
'person_3_type':np.random.randint(4, 8,1000)},
columns= ['person_1_status', 'person_2_status', 'person_3_status',
'person_1_type', 'person_2_type', 'person_3_type'])
person_1_status person_2_status person_3_status person_1_type \
0 1 0 0 7
1 0 1 0 6
2 1 0 1 7
3 0 0 0 7
4 0 0 1 4
person_3_type person_3_type
0 5 5
1 7 7
2 7 7
3 7 7
4 7 7
制作other_table
other_table = pd.Series({4:10, 5:20, 6:30, 7:40})
4 10
5 20
6 30
7 40
dtype: int64
将状态和类型列过滤到它们自己的数据框中
df_status = df.filter(like = 'status')
df_type = df.filter(like = 'type')
进行查找table
df_type_lookup = df_type.applymap(lambda x: other_table.loc[x]).values
跨行应用矩阵乘法和求和。
df['A'] = np.sum((df_status == 0).values * df_type_lookup, 1)
df['B'] = np.sum((df_status == 1).values * df_type_lookup, 1)
输出
person_1_status person_2_status person_3_status person_1_type \
0 0 0 1 7
1 0 1 0 4
2 0 1 1 7
3 0 1 0 6
4 0 0 1 5
person_2_type person_3_type A B
0 7 5 80 20
1 6 4 20 30
2 5 5 40 40
3 6 4 40 30
4 7 5 60 20
考虑数据帧df
mux = pd.MultiIndex.from_product([['status', 'type'], ['p%i' % i for i in range(1, 6)]])
data = np.concatenate([np.random.choice((0, 1), (10, 5)), np.random.rand(10, 5)], axis=1)
df = pd.DataFrame(data, columns=mux)
df
我们可以为type == 1
df.status.mul(df.type).sum(1)
0 0.935290
1 1.252478
2 1.354461
3 1.399357
4 2.102277
5 1.589710
6 0.434147
7 2.553792
8 1.205599
9 1.022305
dtype: float64
和 type == 0
df.status.rsub(1).mul(df.type).sum(1)
0 1.867986
1 1.068045
2 0.653943
3 2.239459
4 0.214523
5 0.734449
6 1.291228
7 0.614539
8 0.849644
9 1.109086
dtype: float64
您可以使用以下代码获取此格式的列
df.columns = df.columns.str.split('_', expand=True)
df = df.swaplevel(0, 1, 1)