有时我在使用Pandas时会得到一系列元组/列表。例如,当执行group-by并传递具有多个返回值的函数时,这很常见:
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?
一个相关的问题是如何将此结构或结果数据框解压缩为两个Series / array对象。这几乎有效:
t, p = zip(*out)
但是t
是
(array(1.3066417475999257),
array(0.08011333825171714),
array(1.557843291126335),
array(0.267999459641651))
并且需要采取额外的步骤来挤压它。
答案 0 :(得分:24)
也许这是最直接的(我猜的大多数是pythonic):
out.apply(pd.Series)
如果您希望将列重命名为更有意义的列,而不是:
out.columns=['Kstats','Pvalue']
如果您不想要索引的默认名称:
out.index.name=None
答案 1 :(得分:12)
也许:
>>> 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]
答案 2 :(得分:9)
我相信你想要这个:
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
答案 3 :(得分:2)
我遇到了类似的问题。我找到了解决它的两种方法正是@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:请原谅我丑陋的代码。