如何解包Pandas中的元组系列?

49 投票
5 回答
42191 浏览
提问于 2025-04-18 00:56

有时候在使用Pandas的时候,我会得到一系列的元组或列表。这种情况很常见,比如在进行分组操作时,传入一个返回多个值的函数:

import numpy as np
from scipy import stats
df = pd.DataFrame(dict(x=np.random.randn(100),
                       y=np.repeat(list("abcd"), 25)))
out = df.groupby("y").x.apply(stats.ttest_1samp, 0)
print out

y
a       (1.3066417476, 0.203717485506)
b    (0.0801133382517, 0.936811414675)
c      (1.55784329113, 0.132360504653)
d     (0.267999459642, 0.790989680709)
dtype: object

那么,怎样才能正确地“拆解”这个结构,让我得到一个有两列的DataFrame呢?

还有一个相关的问题是,如何将这个结构或得到的DataFrame拆解成两个Series或数组对象。这几乎可以做到:

t, p = zip(*out)

但这里的t

 (array(1.3066417475999257),
 array(0.08011333825171714),
 array(1.557843291126335),
 array(0.267999459641651))

所以还需要多做一步,把它压缩一下。

5 个回答

2

我不确定t和r是否在某个地方已经定义过,但如果没有的话,我是通过下面的方式把两个元组传递给t和r的,

>>> t, r = zip(*out)
>>> t
(-1.776982300308175, 0.10543682705459552, -1.7206831272759038, 1.0062163376448068)
>>> r
(0.08824925924534484, 0.9169054844258786, 0.09817788453771065, 0.3243492942246433)

所以,你可以这样做,

>>> df = pd.DataFrame(columns=['t', 'r'])
>>> df.t, df.r = zip(*out)
>>> df
          t         r
0 -1.776982  0.088249
1  0.105437  0.916905
2 -1.720683  0.098178
3  1.006216  0.324349
5

我遇到过类似的问题。我发现解决这个问题的两种方法正好是@CT ZHU和@Siraj S的答案。

这里有一些我觉得你可能感兴趣的补充信息:我比较了这两种方法,发现@CT ZHU的方法在输入数据增大时运行得更快。

举个例子:

#Python 3
import time
from statistics import mean
df_a = pd.DataFrame({'a':range(1000),'b':range(1000)})

#function to test
def func1(x):
    c = str(x)*3
    d = int(x)+100
    return c,d

# Siraj S's way
time_difference = []
for i in range(100):
    start = time.time()
    df_b = df_a['b'].apply(lambda x: func1(x)).apply(pd.Series)
    end = time.time()
    time_difference.append(end-start)

print(mean(time_difference))    
# 0.14907703161239624

# CT ZHU's way
time_difference = []
for i in range(100):
    start = time.time()
    df_b = pd.DataFrame(df_a['b'].apply(lambda x: func1(x)).tolist())
    end = time.time()
    time_difference.append(end-start)    

print(mean(time_difference)) 
# 0.0014058423042297363

PS:请原谅我写的代码不太好看。

18

也许可以这样:

>>> pd.DataFrame(out.tolist(), columns=['out-1','out-2'], index=out.index)
                  out-1     out-2
y                                
a   -1.9153853424536496  0.067433
b     1.277561889173181  0.213624
c  0.062021492729736116  0.951059
d    0.3036745009819999  0.763993

[4 rows x 2 columns]
20

我想你想要的是这个:

df=pd.DataFrame(out.tolist())
df.columns=['KS-stat', 'P-value']

结果:

           KS-stat   P-value
0   -2.12978778869  0.043643
1    3.50655433879  0.001813
2    -1.2221274198  0.233527
3  -0.977154419818  0.338240
65

也许这就是最简单直接的方法(我想这也是最符合Python风格的):

out.apply(pd.Series)

如果你想把列的名字改得更有意义的话,可以这样做:

out.columns=['Kstats','Pvalue']

如果你不想要默认的索引名称,可以这样:

out.index.name=None

撰写回答