如何解包Pandas中的元组系列?
有时候在使用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