【问题标题】:How can I get create new columns in a dataframe that will take care of spillover rows?如何在数据框中创建新列来处理溢出行?
【发布时间】:2021-05-06 01:59:36
【问题描述】:

我有一个看起来像这样的 pandas 数据框:

Name Date Item1 Item2
Andrew 1/1/19 Apple Pear
Andrew 1/1/19 Orange
John 2/5/20 Banana
Steve 2/3/21 Grape Apple

我正在使用的数据框只有 Item1 和 Item2 列,因此如果一个人有第三个项目,则会为该人创建一个具有另一个 Item1 的新行。我想生成相同的 DataFrame,但是通过创建一个 Item3 列并将所有内容保持为每人一行。结果如下所示:

Name Date Item1 Item2 Item3
Andrew 1/1/19 Apple Pear Orange
John 2/5/20 Banana
Steve 2/3/21 Grape Apple

如何在 pandas 中实现这一点?请注意,每人最多可溢出 5 件物品,因此我最多需要 5 件物品。

【问题讨论】:

    标签: python pandas dataframe pivot


    【解决方案1】:
    delimiter = '####'
    dfn = (df.set_index(['Name','Date']).stack()                 # stack to drop NA Item
        .reset_index(name='Item')
        .groupby(['Name','Date'])['Item'].agg(delimiter.join)    # for ('Name', 'Date') grouped, join item by delimiter
        .str.split(delimiter, expand=True)                       # split string, and expand
        .add_prefix('Item')                                      # rename columns with prefix 'Item'
        .reset_index()
    )
    
    print(dfn)
    
    
             Name    Date   Item0  Item1   Item2
        0  Andrew  1/1/19   Apple   Pear  Orange
        1    John  2/5/20  Banana   None    None
        2   Steve  2/3/21   Grape  Apple    None
    

    方法2:

    dfn = df.set_index(['Name','Date']).stack()
    obj = dfn.groupby(level=[0,1]).agg(list)
    df_result = (pd.DataFrame(obj.tolist(), index=obj.index)
                .add_prefix('Item')
                .reset_index())
    
    print(obj)
    
        Name    Date  
        Andrew  1/1/19    [Apple, Pear, Orange]
        John    2/5/20                 [Banana]
        Steve   2/3/21           [Grape, Apple]
        dtype: object
    
    
    print(df_result)
    
            Name    Date   Item0  Item1   Item2
        0  Andrew  1/1/19   Apple   Pear  Orange
        1    John  2/5/20  Banana   None    None
        2   Steve  2/3/21   Grape  Apple    None
    

    【讨论】:

      【解决方案2】:

      一种方法

      • 为名称、日期对生成所有值的列表
      • 将其展开回列
      df = pd.read_csv(io.StringIO("""Name    Date    Item1   Item2
      Andrew  1/1/19  Apple   Pear
      Andrew  1/1/19  Orange  
      John    2/5/20  Banana  
      Steve   2/3/21  Grape   Apple
      """), sep="\t")
      
      # generate a column that is list of values
      df = (df.groupby(["Name","Date"]).agg({c:lambda s: list(s.dropna()) for c in df.columns if "Item" in c}).reset_index()
       .assign(tmp=lambda dfa: dfa.Item1 + dfa.Item2)
       .drop(columns=[c for c in df.columns if "Item" in c])
      )
      
      # expand list into columns
      df = df.loc[:,["Name","Date"]].join( df.tmp.apply(pd.Series).rename(columns={i:f"Item{i+1}" for i in range(5)}))
      
      

      输出

        Name   Date  Item1  Item2 Item3
      Andrew 1/1/19  Apple Orange  Pear
        John 2/5/20 Banana    NaN   NaN
       Steve 2/3/21  Grape  Apple   NaN
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-18
        • 1970-01-01
        • 1970-01-01
        • 2018-11-16
        • 2016-03-11
        • 2018-03-14
        • 2017-07-05
        • 1970-01-01
        相关资源
        最近更新 更多