【问题标题】:how to flatten array in pandas dataframe如何在熊猫数据框中展平数组
【发布时间】:2019-08-03 05:05:37
【问题描述】:

假设我有一个熊猫数据框,例如

df_p = pd.DataFrame(
   {'name_array':
    [[20130101, 320903902, 239032902],
     [20130101, 3253453, 239032902],
     [65756, 4342452, 32425432523]],
    'name': ['a', 'a', 'c']} )

我想提取包含每一行中扁平数组的系列,同时保留顺序

预期结果是pandas.core.series.Series

这个问题不是重复的,因为我的预期输出是熊猫系列,而不是数据框。

【问题讨论】:

  • 那么name 列是无关紧要的?
  • @AlexanderReynolds 是的,这无关紧要。只是数据框的一个示例
  • 不是公认的答案,但第二个显示使用 chain.from_iterable 的答案应该适合你——你只需要将它传递给 Series 而不是 DataFrame 的构造函数.所以:pd.Series(list(chain.from_iterable(df['name_array'])))
  • @AlexanderReynolds 我想出了一种可能的方法(我已将其作为答案发布)。我不知道这是否是一种有效的方法。

标签: python pandas series flatten


【解决方案1】:

使用 melt 的解决方案比 OP 的原始方法慢,他们在答案 here 中分享了这种方法,尤其是在我对该答案的评论加速之后。

我创建了一个更大的数据框进行测试:

df = pd.DataFrame({'name_array': np.random.rand(1000, 3).tolist()})

并在此数据帧产量上使用 melt 对两种解决方案进行计时:

In [16]: %timeit pd.melt(df.name_array.apply(pd.Series).reset_index(), id_vars=['index'],value_name='name_array').drop('variable', axis=1).sort_values('index')
173 ms ± 5.68 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

In [17]: %timeit df['name_array'].apply(lambda x: pd.Series([i for i in x])).melt().drop('variable', axis=1)['value']
175 ms ± 4.86 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

具有我在 cmets 中建议的加速的 OP 方法:

In [18]: %timeit pd.Series(np.concatenate(df['name_array']))
18 ms ± 887 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

最后,here 提供的最快解决方案,但经过修改以提供一系列而不是数据帧输出:

In [14]: from itertools import chain
In [15]: %timeit pd.Series(list(chain.from_iterable(df['name_array'])))
402 µs ± 4.68 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

最后一种方法比 melt() 快 3 个数量级,比 np.concatenate() 快 2 个数量级。

【讨论】:

    【解决方案2】:

    这是我想出的解决方案。不知道有没有更有效的方法。

    df_p = pd.DataFrame(
       {'name_array':
        [[20130101, 320903902, 239032902],
         [20130101, 3253453, 239032902],
         [65756, 4342452, 32425432523]],
        'name': ['a', 'a', 'c']} )
    
    data = pd.DataFrame( {'column':np.concatenate(df_p['name_array'].values)} )['column']
    

    输出:

    [0       20130101
     1      320903902
     2      239032902
     3       20130101
     4        3253453
     5      239032902
     6          65756
     7        4342452
     8    32425432523
     Name: column, dtype: int64]
    

    【讨论】:

    • 您可以删除数据周围的[],因为您只是无缘无故地将新值放入列表中。此外,OP 要求提供一个系列,您正在创建一个数据框,然后使用列名对其进行索引以获得系列——您应该能够在没有中间人的情况下使用 Series() 构造函数本身:)。编辑:大声笑没有意识到你是 OP。
    • 具体来说我是说你可以做到pd.Series(np.concatenate(df_p['name_array']))
    【解决方案3】:

    你可以使用pd.melt:

    pd.melt(df_p.name_array.apply(pd.Series).reset_index(), 
            id_vars=['index'],
            value_name='name_array') \
            .drop('variable', axis=1) \
            .sort_values('index')
    

    输出:

    index   name_array
    0       20130101
    0       320903902
    0       239032902
    1       20130101
    1       3253453
    1       239032902
    2       65756
    2       4342452
    2       32425432523
    

    【讨论】:

      【解决方案4】:

      您可以展平列列表的列表,然后创建一系列列表,以这种方式:

      pd.Series([element for row in df_p.name_array for element in row])
      

      【讨论】:

        猜你喜欢
        • 2021-06-13
        • 1970-01-01
        • 2015-05-17
        • 2020-04-30
        • 2021-07-17
        • 1970-01-01
        • 2016-11-29
        • 2019-03-18
        • 1970-01-01
        相关资源
        最近更新 更多