zab*_*bop 5 python lambda dataframe python-3.x pandas
# import packages, set nan
import pandas as pd
import numpy as np
nan = np.nan
Run Code Online (Sandbox Code Playgroud)
我有一个数据框,有一定数量的观察作为列,测量作为行。该结果的意见是A, B, C, D ...。它也有一个类别列,它表示类别的的测量。分类:a, b, c, d .... 如果一列nan在一行中包含 a ,则意味着尚未进行该测量期间的观察(因此nan不是 an 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)
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
观察值A出现在带有index 0和 的行中3(见上面的 df),而测量值category是a,所以obs_A_in_cat_a也是2。观察A中只出现一次(行index 1)与测量category:b,所以obs_A_in_cat_b是1,等等。
首先我收集观察结果,注意不要包括 nans:
observations = pd.unique(pd.concat([df[col] for col in df.columns if 'observation' in col]).dropna())
Run Code Online (Sandbox Code Playgroud)
它们所属的不同类别:
categories = pd.unique(df['category'])
Run Code Online (Sandbox Code Playgroud)
然后,迭代观察。如果是靠这个,
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)
Run Code Online (Sandbox Code Playgroud)
lambda 函数检查是否observation出现在 each 中row,以及测量值是否在迭代中当前考虑的类别中。创建新列,标题为 obs_OBSERVATION_in_cat_CATEGORY,其中OBSERVATIONis A, B, C, D ...,CATEGORYisa, b, c, d ...如果observationX在categoryY测量期间进行了in a ,obs_OBSERVATIONX_in_cat_CATEGORYY则1在与该测量对应的行中,否则为0。
结果df(部分)如下所示:
完成使用sum()ming 新创建的列的值,选择具有条件列表理解的值:
df[[col for col in df.columns if '_in_cat_' in col]].sum()
Run Code Online (Sandbox Code Playgroud)
这给了我想要得到的输出,如上所示。整个笔记本在这里。
这种方法看似有效,但速度太慢,在现实生活中不易应用。我怎样才能让它更快?我正在寻找类似的东西:
how_many_times_each_observation_was_made_using_each_category_of_measurement(
df,
list_of_observation_columns,
category_column)
Run Code Online (Sandbox Code Playgroud)
解决方案MultiIndexwith DataFrame.melt,GroupBy.size对于计数值,0通过Series.reindex以下方式添加缺失的组合:
s = df.melt('category').groupby(['value','category']).size()
s = s.reindex(pd.MultiIndex.from_product(s.index.levels), fill_value=0)
print (s)
value category
A a 2
b 1
c 1
B a 1
b 2
c 1
C a 1
b 0
c 0
dtype: int64
Run Code Online (Sandbox Code Playgroud)
最后可以通过f-strings 将其展平:
s.index = s.index.map(lambda x: f'obs_{x[0]}_in_cat_{x[1]}')
print (s)
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
dtype: int64
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
95 次 |
| 最近记录: |