【问题标题】:Split dataframe column containing iterable拆分包含可迭代的数据框列
【发布时间】:2018-01-18 23:43:22
【问题描述】:

我有一个 DataFrame,其中一个列包含一些以列表或元组形式的顺序数据(总是相同的长度),我的目标是将此列拆分为几个新列,理想情况下更新其中一个现有列。

这是最简单的例子

from pandas import DataFrame, concat

data = DataFrame({"label": [a for a in "abcde"], "x": range(5)})
print(data)

  label  x
0     a  0
1     b  1
2     c  2
3     d  3
4     e  4

虚构的方式,使用不存在的函数 splittuple 会是这样的

data[["x", "x2"]] = data["x"].apply(lambda x: (x, x*2)).splittuple(expand = True)

导致

  label  x  x2
0     a  0  0
1     b  1  2
2     c  2  4
3     d  3  6
4     e  4  8

我当然可以这样做,虽然解决方案有点麻烦

newdata = DataFrame(data["x"].apply(lambda x: (x, x*2)).tolist(), columns = ["x", "x2"])
data.drop("x", axis = 1, inplace = True)
data = concat((data, newdata), axis = 1)
print(data)

  label  x  x2
0     a  0   0
1     b  1   2
2     c  2   4
3     d  3   6
4     e  4   8

另一种更丑陋的解决方案

data[["x", "x2"]] = 
  data["x"].apply(lambda x: "{} {}".format(x, x*2)).str.split(expand = True).astype(int)

您能否建议更优雅的方式来进行这种类型的转换?

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    applySeries 有可能,但没那么快:

    tup = data["x"].apply(lambda x: (x, x*2))
    data[["x", "x2"]] = tup.apply(pd.Series)
    
    print (data)
      label  x  x2
    0     a  0   0
    1     b  1   2
    2     c  2   4
    3     d  3   6
    4     e  4   8
    

    更快的是使用DataFrame构造函数:

    tup = data["x"].apply(lambda x: (x, x*2))
    data[["x", "x2"]] = pd.DataFrame(tup.values.tolist())
    print (data)
      label  x  x2
    0     a  0   0
    1     b  1   2
    2     c  2   4
    3     d  3   6
    4     e  4   8
    

    时间安排

    data = pd.DataFrame({"label": [a for a in "abcde"], "x": range(5)})
    data = pd.concat([data]*1000).reset_index(drop=True)
    tup = data["x"].apply(lambda x: (x, x*2))
    
    
    data[["x", "x2"]] = tup.apply(pd.Series)
    data[["y", "y2"]] = pd.DataFrame(tup.values.tolist())
    print (data)
    
    In [266]: %timeit data[["x", "x2"]] = tup.apply(pd.Series)
    1 loop, best of 3: 836 ms per loop
    
    In [267]: %timeit data[["y", "y2"]] = pd.DataFrame(tup.values.tolist())
    100 loops, best of 3: 3.1 ms per loop
    

    【讨论】:

    猜你喜欢
    • 2020-09-28
    • 2019-07-25
    • 1970-01-01
    • 2021-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-03-03
    相关资源
    最近更新 更多