【问题标题】:How to get first 3 elements with values per ordered row in Python如何在Python中获取每个有序行的值的前3个元素
【发布时间】:2021-06-11 23:25:53
【问题描述】:

我有一个数据类型为字符串的 DataFrame,如下所示:

ID Var1 Var2 Var3 Var4 Var5
1 A B C D E
2 B C D
3 C D E
4 A C E

我想为每一行选择前 3 个元素,如下所示:

ID Var1 Var2 Var3 Var4 Var5 Var6
1 A B C D E A,B,C
2 B C D B,C,D
3 C D E C,D,E
4 A C E A,C,E

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    试试这个:

    df['Var6'] = df.apply(lambda x: [y for y in x.values if y != ''][:3], axis=1)
    

    结果df:

      Var1 Var2 Var3 Var4 Var5       Var6
    1    A    B    C    D    E  [A, B, C]
    2         B    C    D       [B, C, D]
    3              C    D    E  [C, D, E]
    4    A         C         E  [A, C, E]
    

    如果您希望结果为逗号分隔的字符串,请进一步使用:

    df['Var6'] = df['Var6'].str.join(', ')
    

    结果df:

      Var1 Var2 Var3 Var4 Var5     Var6
    1    A    B    C    D    E  A, B, C
    2         B    C    D       B, C, D
    3              C    D    E  C, D, E
    4    A         C         E  A, C, E
    

    如果您想一步完成,请使用:

    df['Var6'] = df.apply(lambda x: ','.join([y for y in x.values if y != ''][:3]), axis=1)
    

    编辑

    当我提供答案时,我将示例数据中的 ID 解释为行索引,特别是当 OP 提到 DataFrame 的数据类型为字符串并且她从每行中选择前 3 个元素时,列中的值标记为ID 未被选中。

    但是,我看到其他一些答案将ID 视为数据列。为了完整起见,我想添加代码,以防ID 是一个数据列,而它的值仍然不能为每行中的前 3 个元素选择。

    如果ID是数据列但不能被选中:稍微调整代码如下:

    df1 = df.set_index('ID')      # temporarily set column ID as index
    # same code as my main answer except to replace df by df1
    df1['Var6'] = df1.apply(lambda x: ','.join([y for y in x.values if y != ''][:3]), axis=1)
    df = df1.reset_index()        # reset the index to move ID back to data column 
    

    【讨论】:

      【解决方案2】:

      利用df.values.tolist()的替代解决方案

      import pandas as pd
      # Working example with empty strings 
      df = pd.DataFrame({"Var1": ["A", "", "", "A"],
                         "Var2": ["B", "B",  "", ""],
                         "Var3": ["C",  "C", "C", "C"],
                         "Var4": ["D", "D", "D", ""],
                         "Var5": ["E", "", "E", "E"]
                        })
      df["Var6"] = df.values.tolist()
      df["Var6"] = df["Var6"].map(lambda x: ",".join([i for i in x if i != ""][:3]))
      df
      
      # Working example with None
      df = pd.DataFrame({"Var1": ["A", None, None, "A"],
                         "Var2": ["B", "B",  None, None],
                         "Var3": ["C",  "C", "C", "C"],
                         "Var4": ["D", "D", "D", None],
                         "Var5": ["E", None, "E", "E"]
                        })
      df["Var6"] = df.values.tolist()
      df["Var6"] = df["Var6"].map(lambda x: ",".join([i for i in x if i is not None][:3]))
      df
      

      【讨论】:

        【解决方案3】:

        您可以将stackgroupby.head(3) 和链groupby.agg(','.join) 一起使用

        df['var6'] = df.set_index('ID',append=True)\
                       .stack().groupby(level=[0]).head(3)\
                               .groupby(level=0).agg(','.join)
        
        print(df)
        
           ID Var1 Var2 Var3 Var4 Var5   var6
        0   1    A    B    C    D    E  A,B,C
        1   2  NaN    B    C    D  NaN  B,C,D
        2   3  NaN  NaN    C    D    E  C,D,E
        3   4    A  NaN    C  NaN    E  A,C,E
        

        【讨论】:

        • @ShubhamSharma BeNY 也击败了我 - 谢谢,这是有道理的!
        【解决方案4】:

        试试stack 然后groupby head

        df['out'] = df.stack().loc[lambda x : x!=''].groupby(level=0).head(3).groupby(level=0).agg(','.join)
        Out[277]: 
        0    A,B,C
        1    B,C,D
        2    C,D,E
        3    A,C,E
        dtype: object
        

        或者

        df.where(df=='',df+',').sum(1).str[:5]
        Out[282]: 
        0    A,B,C
        1    B,C,D
        2    C,D,E
        3    A,C,E
        dtype: object
        

        【讨论】:

          猜你喜欢
          • 2015-07-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-17
          • 2023-04-07
          • 1970-01-01
          • 2014-09-22
          • 1970-01-01
          相关资源
          最近更新 更多