熊猫:以不同的方式对每列进行分组

时间:2019-01-22 11:49:28

标签: python pandas pandas-groupby

假设我有以下数据框:

df = pd.DataFrame({"unique_id": [1, 1, 1], "att1_amr": [11, 11, 11], "att2_nominal": [1, np.nan, np.nan], "att3_nominal": [np.nan, 1, np.nan], "att4_bok": [33.33, 33.33, 33.33], "att5_nominal": [np.nan, np.nan, np.nan], "att6_zpq": [22.22, 22.22, 22.22]})

我想做的是按unique_id对数据帧的行进行分组,这样我就可以对包含单词nominal和a的列进行单独的分组操作。彼此分开。更具体地说,我想使用nominal对包含sum(min_count = 1)的列进行分组,而其他列则使用first()last()进行分组。结果应为以下内容:

df_result = pd.DataFrame({"unique_id": [1], "att1_amr": [11], "att2_nominal": [1], "att3_nominal": [1], "att4_bok": [33.33], "att5_nominal": [np.nan], "att6_zpq": [22.22]})

谢谢!

3 个答案:

答案 0 :(得分:2)

您可以动态创建字典-首先使用具有lambda函数的nominal的所有列,然后使用last的所有其他列并将其合并在一起,最后调用DataFrameGroupBy.agg

d1 = dict.fromkeys(df.columns[df.columns.str.contains('nominal')], 
                   lambda x : x.sum(min_count=1))

d2 = dict.fromkeys(df.columns.difference(['unique_id'] + list(d1)), 'last')
d = {**d1, **d2}

df = df.groupby('unique_id').agg(d)
print (df)
           att2_nominal  att3_nominal  att5_nominal  att1_amr  att4_bok  \
unique_id                                                                 
1                   1.0           1.0           NaN        11     33.33   

           att6_zpq  
unique_id            
1             22.22  

另一个更清洁的解决方案:

d = {k: (lambda x : x.sum(min_count=1)) 
     if 'nominal' in k 
     else 'last' 
     for k in df.columns.difference(['unique_id'])}

df = df.groupby('unique_id').agg(d)
print (df)
           att1_amr  att2_nominal  att3_nominal  att4_bok  att5_nominal  \
unique_id                                                                 
1                11           1.0           1.0     33.33           NaN   

           att6_zpq  
unique_id            
1             22.22  

答案 1 :(得分:0)

为什么不只是:

ionViewDidLoad() {
  this.timer = setInterval(() => this.setTimeElapsed(), 1000);
}

setTimeElapsed() {
  let now = new Date().getTime();
  let difference = now - this.timestamp;

  let days = Math.floor(difference / (1000 * 60 * 60 * 24));
  let hours = Math.floor((difference % (1000 * 60 * 60 * 24)) / (1000 * 60 * 24));
  let minutes = Math.floor((difference % (1000 * 60 * 60)) / (1000 * 60));
  let seconds = Math.floor((difference % (1000 * 60)) / 1000);

  this.time_elapsed = `${days} d ${hours} h ${minutes} m ${seconds} s`;
}

restart() {
  clearInterval(this.timer);
  this.timer = setInterval(() => this.setTimeElapsed(), 1000);
}

答案 2 :(得分:0)

@jezrael提供的解决方案虽然是最优雅的,但效果很好,但是我遇到了严重的性能问题。令人惊讶的是,我发现这是实现相同目标的更快解决方案。

nominal_cols = df.filter(like="nominal").columns.values
other_cols = [col for col in df.columns.values if col not in nominal_cols and col != "unique_id"]
df1 = df.groupby('unique_id', as_index=False)[nominal_cols].sum(min_count=1)
df2 = df.groupby('unique_id', as_index=False)[other_cols].first()
pd.merge(df1, df2, on=["unique_id"], how="inner")