【问题标题】:How to turn a pandas dataframe row into a comma separated value with condition如何将熊猫数据框行转换为带条件的逗号分隔值
【发布时间】:2022-01-25 20:31:42
【问题描述】:

我有一个这样的熊猫数据框:

id =[30,30,40,40,30,40,55,30]
month =[1,3,11,4,10,2,12,12]
average=[90,80,50,92,18,15,16,55]
sec =['id1','id1','id3','id4','id2','id2','id1','id1']

df = pd.DataFrame(list(zip(id,sec,month,average)),columns =['id','sec','month','Average'])

我们想再添加一列,以逗号分隔以下条件的月份

  1. 需要排除 id2 秒
  2. 平均低于 90

期望的输出

我尝试了下面的代码,但没有得到想要的输出

final=pd.DataFrame()
for i in set(sec):
  if i !='id2': #Exclude id2
    d2 =df[df['sec']==i]
    d2=df[df['average']<90]  # apply below 90 condition
    d2=d2[['id','month']].groupby(['id'], as_index=False).agg(lambda x: ', '.join(sorted(set(x.astype(str))))) #comma seperated data
    d2.rename(columns={'month':'problematic_month'},inplace=True)
    d2['sec']=i
    tab =df.merge(d2,on =['id','sec'], how ='inner')
    final =final.append(tab)
  else:
    d2 =df[df['sec']==i]
    d2['problematic_month']=np.NaN
    final =final.append(d2)

请建议任何其他方式(不合并)以获得所需的输出

【问题讨论】:

  • 能否请您添加数据框所需的输出?
  • 你不想使用merge吗?

标签: python pandas


【解决方案1】:

使用groupby+transform的另一种方式

import calendar
d = dict(enumerate(calendar.month_abbr))

s = df['month'].map(d).where(df['sec'].ne("id2")& (df['Average'].lt(90)))
col = s.groupby([df["id"],df['sec']]).transform(lambda x: ','.join(x.dropna()))

out = df.assign(problematic_column=col.replace("",np.nan)).sort_values(['id','sec'])

print(out)

   id  sec  month  Average problematic_column
0  30  id1      1       90            Mar,Dec
1  30  id1      3       80            Mar,Dec
7  30  id1     12       55            Mar,Dec
4  30  id2     10       18                NaN
5  40  id2      2       15                NaN
2  40  id3     11       50                Nov
3  40  id4      4       92                NaN
6  55  id1     12       16                Dec

步骤:

  1. 将月份列映射到日历以获取月份缩写。
  2. 仅当条件匹配时才保留值。
  3. 使用 groupby 并转换为 dropna 并以逗号加入。

【讨论】:

    【解决方案2】:

    您可以首先使用 calendar 将您的 int 月份转换为实际的月份缩写。

    df['month'] = df['month'].apply(lambda x: calendar.month_abbr[x])
    
    print(df.head(3))
    
       id  sec month  Average
    0  30  id1   Jan       90
    1  30  id1   Mar       80
    2  40  id3   Nov       50
    

    然后我会使用loc 根据您的上述条件和groupby 来缩小您的数据框,并让您的月份每秒都在一起。

    之后使用map 将其附加到您的初始数据框:

    r = df.loc[(df['Average'].gt(90) |\
               (df['sec'].eq('id2'))).eq(0)]\
        .groupby('sec').agg({'month':lambda x: ','.join(x)})\
        .reset_index()\
            .rename({'month':'problematic_month'},axis=1)
    
    print(r)
    
       sec problematic_month
    0  id1       Jan,Mar,Dec
    1  id3               Nov
    
    # Attach with map
    df['problematic_month'] = df['sec'].map(dict(zip(r.sec,r.problematic_month)))
    
    >>> print(df)
    
       id  sec month  Average problematic_month
    0  30  id1   Jan       90       Jan,Mar,Dec
    1  30  id1   Mar       80       Jan,Mar,Dec
    2  40  id3   Nov       50               Nov
    3  40  id4   Apr       92               NaN
    4  30  id2   Oct       18               NaN
    5  40  id2   Feb       15               NaN
    6  55  id1   Dec       16       Jan,Mar,Dec
    

    然后使用这个有问题的_month 列,您可以检查它是否包含,,并且您可以选择第一列和最后一列:

    import numpy as np
    f = df['problematic_month'].str.split(',').str[0] 
    l = ',' +  df['problematic_month'].str.split(',').str[-1]
    
    df['problematic_month'] = np.where(df['problematic_month'].str.contains(','),f+l, df['problematic_month'])
    

    答案:

    >>> print(df)
    
       id  sec month  Average problematic_month
    0  30  id1   Jan       90           Jan,Dec
    1  30  id1   Mar       80           Jan,Dec
    2  40  id3   Nov       50               Nov
    3  40  id4   Apr       92               NaN
    4  30  id2   Oct       18               NaN
    5  40  id2   Feb       15               NaN
    6  55  id1   Dec       16           Jan,Dec
    

    【讨论】:

      猜你喜欢
      • 2015-11-20
      • 2021-12-06
      • 1970-01-01
      • 2022-10-07
      • 2020-04-04
      • 1970-01-01
      • 1970-01-01
      • 2022-01-19
      • 1970-01-01
      相关资源
      最近更新 更多