【问题标题】:Accessing every 1st element of Pandas DataFrame column containing lists访问包含列表的 Pandas DataFrame 列的每个第一个元素
【发布时间】:2016-05-09 20:47:57
【问题描述】:

我有一个 Pandas DataFrame,其中有一列包含列表对象

      A
0   [1,2]
1   [3,4]
2   [8,9] 
3   [2,6]

如何访问每个列表的第一个元素并将其保存到 DataFrame 的新列中?要得到这样的结果:

      A     new_col
0   [1,2]      1
1   [3,4]      3
2   [8,9]      8
3   [2,6]      2

我知道这可以通过遍历每一行来完成,但是有没有“pythonic”的方式?

【问题讨论】:

    标签: python pandas dataframe


    【解决方案1】:

    与往常一样,请记住,在帧中存储非标量对象通常是不受欢迎的,实际上应该仅用作临时中间步骤。

    也就是说,您可以使用 .str 访问器,即使它不是字符串列:

    >>> df = pd.DataFrame({"A": [[1,2],[3,4],[8,9],[2,6]]})
    >>> df["new_col"] = df["A"].str[0]
    >>> df
            A  new_col
    0  [1, 2]        1
    1  [3, 4]        3
    2  [8, 9]        8
    3  [2, 6]        2
    >>> df["new_col"]
    0    1
    1    3
    2    8
    3    2
    Name: new_col, dtype: int64
    

    【讨论】:

    • 这实际上只是暂时的,因为我在这些列中的字符串上使用了 '.split()'。感谢您的快速帮助!
    • 我坚持这是最优雅的解决方案,但在长度为 500 万的系列中,每个元素只是一个包含 2 个元素的列表,.str[idx] 方法需要 3.31 秒,而 .apply(lambda x: x[idx]) 耗时 1.43 秒
    • 这可能比通过 .apply() 慢,但它可以优雅地处理 NaN 值(即,它将 NaN 保留为 NaN 而不会引发错误)。
    【解决方案2】:

    您可以使用maplambda 函数

    df.loc[:, 'new_col'] = df.A.map(lambda x: x[0])
    

    【讨论】:

    • 在我的情况下,代码在您的解决方案中运行时间最短。感谢您的帮助!
    • 但如果您需要它来处理 NaN 值,请参阅 DSM 的回复。
    【解决方案3】:

    applyx[0] 一起使用:

    df['new_col'] = df.A.apply(lambda x: x[0])
    print df
            A  new_col
    0  [1, 2]        1
    1  [3, 4]        3
    2  [8, 9]        8
    3  [2, 6]        2
    

    【讨论】:

      【解决方案4】:

      您可以只使用条件列表推导式,它采用任何可迭代的第一个值,或者对该项目使用 None 。列表推导非常 Pythonic。

      df['new_col'] = [val[0] if hasattr(val, '__iter__') else None for val in df["A"]]
      
      >>> df
              A  new_col
      0  [1, 2]        1
      1  [3, 4]        3
      2  [8, 9]        8
      3  [2, 6]        2
      

      时间

      df = pd.concat([df] * 10000)
      
      %timeit df['new_col'] = [val[0] if hasattr(val, '__iter__') else None for val in df["A"]]
      100 loops, best of 3: 13.2 ms per loop
      
      %timeit df["new_col"] = df["A"].str[0]
      100 loops, best of 3: 15.3 ms per loop
      
      %timeit df['new_col'] = df.A.apply(lambda x: x[0])
      100 loops, best of 3: 12.1 ms per loop
      
      %timeit df.A.map(lambda x: x[0])
      100 loops, best of 3: 11.1 ms per loop
      

      删除确保可交互性的安全检查。

      %timeit df['new_col'] = [val[0] for val in df["A"]]
      100 loops, best of 3: 7.38 ms per loop
      

      【讨论】:

      • 请注意 hasattr(..., '__iter__') 不是一个神奇的列表标识符,它也适用于字符串,例如hasattr('hello', '__iter__') 返回True,这可能不是你想要的。
      【解决方案5】:

      可以使用str.get的方法:

      df['A'].str.get(0)
      

      【讨论】:

        猜你喜欢
        • 2016-10-31
        • 2013-05-24
        • 2021-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-07
        相关资源
        最近更新 更多