【问题标题】:Python data frame apply filter on multiple columns with same condition?Python数据框对具有相同条件的多列应用过滤器?
【发布时间】:2016-09-16 08:28:12
【问题描述】:

这是我的熊猫数据框。

new_data =

    name   duration01        duration02          orz01      orz02     
    ABC   1 years 6 months    5 months           Nan        Google     
    XYZ   4 months            3 years 2 months   Google      Zensar      
    TYZ   4 months            4 years            Google In   Google   
    OPI   2 months            3 months           Nan       accenture    
    NRM   9 months            3 years            Google      Zensar     

我想找出在 Google 工作的员工的姓名以及工作时间(以月为单位)。这里的值包含在多个列中吗?如何在多列上应用过滤器?

duration01 => orz01(员工在 orz01 中花费的月/年) duration02 => orz02(员工在 orz02 中花费的月/年)

共有 10 个 orz 和 10 个相应的持续时间列。

我试过下面的代码

# Selected the required columns
orz_cols = new_data.columns[new_data.columns.str.contains('orz')]

new_data [ new_data[orz_cols].apply(lambda x: x.str.contains('Google')) ]

但它没有打印正确的数据?

我是怎么做到的

我想要像下面这样的输出

name  Total_duration_in Google_in_Months
ABC   5 months
XYZ   4 months
TYZ   52 months  

使用@Stefan 给出的第一部分我在下面所做的将年转换为月

# filter the data

Google_Data = dt1[dt1['orz'].str.contains('Google')]

dur = []

for i in range(0,len(Google_Data['duration'])):
    dur.append(Google_Data['duration'][i].split())

months_list = []

for i in range(0,len(dur)):
    #print dur[i]
    if dur[i][1] == 'years':
        if len(dur[i]) > 2:
            val1 = int(dur[i][0]) * 12 + int(dur[i][2])
            val11 = str(val1)+" months"
            months_list.append(val11)
        else:
            val2 = int(dur[i][0]) * 12
            val22 = str(val2)+" months"
            months_list.append(val22)
    else:
        val3 = dur[i][0]+" months"
        months_list.append(val3)

months_list[:3]

# Concat
df2 = pd.DataFrame(months_list,index=Google_Data.index.copy())

Google_duration = pd.concat([Google_Data, df2], axis=1)


Output :

                    organization                      Duration_In_Months
name        
Aparna Arora        Google Headstrong Capital Markets   60 months
Aparna Dasgupta     Google                              24 months
Aparna Dhar         Google India Ltd                    56 months

现在我想执行最后一步,即通过对名称进行分组来求和,但这里的“名称”是索引。我很难得到总和。

这是我正在尝试的

# Splitting the Duration_In_Months to get only number values
# Its returning the type as 'str'

Google_duration1 = Google_duration.Duration_In_Months.apply(lambda x : x.split()[0])

# apply groupby

Genpact_dur2.index.groupby(Genpact_dur2['Duration_In_Months'])

我如何 Groupby 索引并取总和?

谢谢,

【问题讨论】:

    标签: python pandas filter group-by multiple-columns


    【解决方案1】:

    考虑使用pandas.melt 进行整形,然后使用np.where() 有条件地解析出年份和月份的值。最后,由 Google 组织汇总。

    import pandas as pd
    import numpy as np
    
    ...
    # LIST OF SUBSET COLUMNS
    durationCols = [c for c in df.columns if 'duration' in c ]
    orzCols = [c for c in df.columns if 'orz' in c ]
    
    # MELT AND MERGE
    df = pd.merge(pd.melt(df, id_vars=['name'], value_vars=durationCols,
                      var_name=None, value_name='duration'),
                  pd.melt(df, id_vars=['name'], value_vars=orzCols,
                      var_name=None, value_name='orz'),
                  right_index=True, left_index=True, on=['name'])[['name', 'duration', 'orz']]
    
    # DURATION CONDITIONAL CALCULATION (YEAR + MONTH)
    df['actual_dur'] = np.where(df['duration'].str.contains('year'),
                                df['duration'].str[:1], 0).astype(int) * 12 + \
                       np.where(df['duration'].str.contains('year.*month'),
                                df['duration'].str[8:9],
                                np.where(df['duration'].str.contains('month'),
                                         df['duration'].str[:1], 0)).astype(int)
    
    df['orz'] = np.where(df['orz']\
                         .str.contains('Google'), 'Google', df['orz'])    
    
    # SUM DURATION AND OUTPUT DF
    df = df[df['orz']=='Google'].groupby(['name','orz']).sum().reset_index()    
    df = df[['name','actual_dur']]
    df.columns = ['name', 'Total_duration_in Google_in_Months']
    

    输出

    #   name  Total_duration_in Google_in_Months
    # 0  ABC                                   5
    # 1  NRM                                   9
    # 2  TYZ                                  52
    # 3  XYZ                                   4    
    

    【讨论】:

    • 感谢它的工作正常,但在逐月计算步骤后我得到了奇怪的值。以下是特定名称的值。
    • 使用实际数据可能会导致问题。持续时间是否包含以年/月为单位的单个数字以外的内容?可能是多位数?
    • 我已将此部分位 df['duration'].str[:1], 0).astype(int) * 12 更改为 `df['duration'].str[:2], 0).astype(int) * 12` 所以它可以处理像 10 或11 但我得到的奇数值是像“2年”这样的持续时间输入。
    • 实际上我在计算之前将持续时间列中的“Nan”和“Present”条目分别替换为“1 year”和“2 year”。但是,这些值并没有给出奇数。我会再次检查并让您知道。我认为一些导致问题的数据问题,如“月”和“年”在其他语言中有很多名称。我正在使用替换替换这些值,但有很多这样不同的名称。我想知道是否有任何 python 日历字典,所以我只是用英语查找并替换那些。抱歉在这里问这个问题。脚本工作正常。我接受答案。谢谢。
    【解决方案2】:

    你可以这样做:

    设置index 并获取columns 组合:

    df.set_index('name', inplace=True)    
    orz_cols = [col for col in df.columns if col.startswith('orz')]
    duration_cols = [col for col in df.columns if col.startswith('duration')]
    merge_cols = zip(orz_cols, duration_cols)
    

    使用pd.concat() 重塑和重命名:

    long_df = pd.concat([df.loc[:, cols].rename(columns={col: col[:-2] for col in orz_cols + duration_cols}) for cols in merge_cols])
    

    消除非 Google orz 条目:

    long_df = long_df[long_df.orz.str.contains('Google')]
    

    根据monthyear 计算duration

    long_df.duration = long_df.duration.str.split().apply(lambda x: int(x[0]) if x[1] == 'months' else int(x[0]) * 12)
    

    求和name:

    long_df.groupby(level='name')['duration'].sum()
          duration
    name          
    ABC          5
    NRM          9
    TYZ         52
    XYZ          4
    

    【讨论】:

    • 他想要一个结果 groupby().sum()
    • 加字符串解析。
    • 我不想提及它,因为它与熊猫无关。你不应该完全抱着他的孩子:)
    • @Stefan 第一部分工作正常,但第二部分出现错误ValueError: invalid literal for int() with base 10: 'less'
    • Google = dt1[dt1['organization'].str.contains('Google')]我过滤了orz的数据
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-19
    • 1970-01-01
    • 2018-09-18
    • 2017-10-11
    相关资源
    最近更新 更多