【发布时间】:2020-11-24 13:54:16
【问题描述】:
# import packages, set nan
import pandas as pd
import numpy as np
nan = np.nan
问题
我有一个数据框,有一定数量的 observations 作为列,measurements 作为行。 观察的结果是A, B, C, D ...。它还有一个 category 列,表示 measurement 的 category。分类:a, b, c, d ...。如果一列连续包含nan,则表示尚未进行该测量期间的观察(因此nan 不是observation,它缺少它)。一个MRE:
data = {'observation0': ['A','A','A','A','B'],'observation1': ['B','B','B','C',nan], 'category': ['a', 'b', 'c','a','b']}
df = pd.DataFrame.from_dict(data)
df 看起来像这样:
我想计算使用每种测量类别(即a, b, c, d ...)观察每个观察结果(即A, B, C, D...)的次数。
我想得到:
obs_A_in_cat_a 2
obs_A_in_cat_b 1
obs_A_in_cat_c 1
obs_B_in_cat_a 1
obs_B_in_cat_b 2
obs_B_in_cat_c 1
obs_C_in_cat_a 1
obs_C_in_cat_b 0
obs_C_in_cat_c 0
观察A 与index 0 和3 成行出现(见上面的df),而测量category 是a,所以obs_A_in_cat_a 是2。观测值A 在category 的测量中只出现一次(行index 1):b,所以obs_A_in_cat_b 是1,依此类推。
我的解决方案
首先我收集观察结果,taking care not to include nans:
observations = pd.unique(pd.concat([df[col] for col in df.columns if 'observation' in col]).dropna())
它们所属的不同类别:
categories = pd.unique(df['category'])
然后,遍历观察。如果是依赖this,
for observation in observations:
for category in categories:
df['obs_'+observation+'_in_cat_'+category]=\
df.apply(lambda row: int(observation in [row[col]
for col in df.columns
if 'observation' in col]
and row['category'] == category),axis=1)
lambda 函数检查observation 是否出现在每个row 中,以及测量是否属于当前在迭代中考虑的类别。创建新列,标题为 obs_OBSERVATION_in_cat_CATEGORY,其中 OBSERVATION 是 A, B, C, D ...,CATEGORY 是 a, b, c, d ... 如果在测量期间创建了 categoryY 中的 observationX,则 obs_OBSERVATIONX_in_cat_CATEGORYY 中的 @98765436对应于该度量的行,否则为0。
生成的df(部分)如下所示:
使用sum()ming 完成新创建列的值,选择带有conditional list comprehension 的列:
df[[col for col in df.columns if '_in_cat_' in col]].sum()
这给了我想要得到的输出,如上所示。 Whole notebook here.
问题
这种方法似乎有效,但速度太慢,无法在现实生活中轻松应用。我怎样才能让它更快?我正在寻找类似的东西:
how_many_times_each_observation_was_made_using_each_category_of_measurement(
df,
list_of_observation_columns,
category_column)
【问题讨论】:
标签: python python-3.x pandas dataframe lambda