【问题标题】:How to split single column of pandas dataframe into multiple columns with group?如何将熊猫数据框的单列拆分为多列与组?
【发布时间】:2017-09-11 05:53:47
【问题描述】:

我是 python pandas 的新手。我有一个如下数据框:

df = pd.DataFrame({'Name': ['football', 'ramesh','suresh','pankaj','cricket','rakesh','mohit','mahesh'],
               'age': ['25', '22','21','32','37','26','24','30']})
print df

       Name age
0  football  25
1    ramesh  22
2    suresh  21
3    pankaj  32
4   cricket  37
5    rakesh  26
6     mohit  24
7    mahesh  30

“姓名”栏还包含“运动名称”和“运动人姓名”。我想把它分成两个不同的列,如下所示:

预期输出:

sports_name sport_person_name age
football    ramesh            25
            suresh            22
            pankaj            32
cricket     rakesh            26
            mohit             24
            mahesh            30

如果我在“名称”列上进行分组,我不会得到预期的输出,这显然是直接的输出,因为“名称”列中没有重复。我需要使用什么才能获得预期的输出?

编辑:如果不想硬编码运动名称

df = pd.DataFrame({'Name': ['football', 'ramesh','suresh','pankaj','cricket','rakesh','mohit','mahesh'],
           'age': ['', '22','21','32','','26','24','30']})

df = df.replace('', np.nan, regex=True)

nan_rows = df[df.isnull().T.any().T]
sports = nan_rows['Name'].tolist()

df['sports_name'] = df['Name'].where(df['Name'].isin(sports)).ffill()
d = {'Name':'sport_person_name'}
df = df[df['sports_name'] != df['Name']].reset_index(drop=True).rename(columns=d)
df = df[['sports_name','sport_person_name','age']]
print (df)

我刚刚检查了除了“名称”列之外的行在所有其余列中都包含 NAN 值,并且肯定是体育名称。我创建了该运动名称的列表,并利用以下解决方案创建了 sports_name 和 sports_person_name 列。

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    你可以使用:

    #define list of sports
    sports = ['football','cricket']
    #create NaNs if no sport in Name, forward filling NaNs
    df['sports_name'] = df['Name'].where(df['Name'].isin(sports)).ffill()
    #remove same values in columns sports_name and Name, rename column
    d = {'Name':'sport_person_name'}
    df = df[df['sports_name'] != df['Name']].reset_index(drop=True).rename(columns=d)
    #change order of columns
    df = df[['sports_name','sport_person_name','age']]
    print (df)
      sports_name sport_person_name age
    0    football            ramesh  22
    1    football            suresh  21
    2    football            pankaj  32
    3     cricket            rakesh  26
    4     cricket             mohit  24
    5     cricket            mahesh  30
    

    DataFrame.insert 类似的解决方案 - 然后不需要重新排序:

    #define list of sports
    sports = ['football','cricket']
    #rename column by dict
    d = {'Name':'sport_person_name'}
    df = df.rename(columns=d)
    #create NaNs if no sport in Name, forward filling NaNs
    df.insert(0, 'sports_name', df['sport_person_name'].where(df['sport_person_name'].isin(sports)).ffill())
    #remove same values in columns sports_name and Name
    df = df[df['sports_name'] != df['sport_person_name']].reset_index(drop=True)
    print (df)
      sports_name sport_person_name age
    0    football            ramesh  22
    1    football            suresh  21
    2    football            pankaj  32
    3     cricket            rakesh  26
    4     cricket             mohit  24
    5     cricket            mahesh  30
    

    如果只需要一个运动值,请将limit=1 添加到ffill 并将NaNs 替换为空字符串:

    sports = ['football','cricket']
    df['sports_name'] = df['Name'].where(df['Name'].isin(sports)).ffill(limit=1).fillna('')
    d = {'Name':'sport_person_name'}
    df = df[df['sports_name'] != df['Name']].reset_index(drop=True).rename(columns=d)
    df = df[['sports_name','sport_person_name','age']]
    print (df)
      sports_name sport_person_name age
    0    football            ramesh  22
    1                        suresh  21
    2                        pankaj  32
    3     cricket            rakesh  26
    4                         mohit  24
    5                        mahesh  30
    

    【讨论】:

    • @jezrael- 感谢您的回答。如果我不想在代码中硬编码运动名称。如果它会动态变化,那么我们手中的选择是什么?
    • 嗯,有问题。因为从names 查找运动的逻辑如何?
    • 是的,看看我的实际问题。它是一个数据透视表。如果您对在 pandas 中读取数据透视表有任何想法,请给我一些提示。 stackoverflow.com/questions/46154843/…?
    • 也许一些可能的解决方案是从维基百科创建一些所有现有运动的大列表 - 但不确定是否与您的所有数据匹配。
    • @jazrael- 不,它没有生产力。它对我不起作用。
    【解决方案2】:

    您想要的输出是字典而不是数据框。 字典会看起来:

    {'Sport' : {'Player' : age,'Player2' : age}}
    

    如果你真的想要一个数据框: 如果名字总是出现在玩家之前:

    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame({'Name': ['football','ramesh','suresh','pankaj','cricket' 
                      ,'rakesh','mohit','mahesh'],
                      'age': ['25', '22','21','32','37','26','24','30']})
    
    sports=['football', 'cricket']
    wanted_dict={}
    current_sport=''
    
    for val in df['sport_person_name']:
        if val in sports:
            current_sport=val
        else:
            wanted_dict[val]=current_sport
    
    #Now you got - {name:sport_name,...}
    
    df['sports_name']=999
    for val in df['sport_person_name']
        df['sports_name']=np.where((val not in sports)&
                                  (df['sport_person_name']==val),
                                   wanted_dict[val],'sport)
    
    df = df[df['sports_name']!='sport']
    

    应该是什么样子:

    sports_name sport_person_name age
    football    ramesh            25
    football    suresh            22
    football    pankaj            32
    cricket     rakesh            26
    cricket     mohit             24
    cricket     mahesh            30
    

    【讨论】:

    • @Drzaloren- 感谢您的回答。如果我不想在代码中硬编码运动名称。如果它会动态变化,那么我们手中的选择是什么?
    • 好吧,如果你有一项运动,而且人数相同,你可以使用索引来创建运动列表,我看到你有一个年龄列,那么运动会写什么?如果一项运动的值为 NaN,您可以尝试使用它。
    • @Drzaloren- 是的,你是对的。看到正确的数据框这个 - df = pd.DataFrame({'Name': ['football', 'ramesh','suresh','pankaj','cricket','rakesh','mohit','mahesh'] , 'age': ['', '22','21','32','','26','24','30']}) 但不要硬编码年龄列是空代码,因为我此数据框还有 100 列对于运动行为空。
    • 不确定我是否理解。如果年龄对于一项运动总是为空,而对于一个球员来说,'int' 你可以这样做: Df2=df Df2.fillna(999) Df2=df[df['age']==999] 而不是 df2[ '名称'] 作为您的运动列表
    • @Drzaloren- 请参阅问题中的编辑。感谢您的快速提示。
    猜你喜欢
    • 2018-12-04
    • 2021-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-03
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    相关资源
    最近更新 更多