Python 如何解包熊猫中的一系列元组?

Python 如何解包熊猫中的一系列元组?,python,pandas,Python,Pandas,有时我在使用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_1

有时我在使用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
什么是“解包”此结构的正确方法,以便获得具有两列的数据帧

一个相关的问题是如何将此结构或生成的数据帧解包为两个Series/array对象。这几乎奏效了:

t, p = zip(*out)
但是它是

 (array(1.3066417475999257),
 array(0.08011333825171714),
 array(1.557843291126335),
 array(0.267999459641651))
人们需要采取额外的措施来挤压它。

也许:

>>> 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]

我相信你想要这个:

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

也许这是最具挑战性的(我想是最具蟒蛇精神的):

如果要将列重命名为更有意义的名称,请执行以下操作:

out.columns=['Kstats','Pvalue']
如果不需要索引的默认名称:

out.index.name=None

我也遇到过类似的问题。我找到的两种解决方法正是@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:请原谅我丑陋的代码

df.groupby(“y”).x.apply(lambda x,y:pd.Series(stats.ttest_1amp(x,y),['A','B']),0)。unstack()有点混乱(需要知道输入的长度)。切换正确答案,因为我同意这是最干净的。实际上,使用
out.apply(pd.Series,index)一次操作也可以获得正确的列名=[“stat,”p“])
根据文档,
Series.apply(func)
如果
func
返回一个系列,则返回一个数据帧。
out.apply(pd.Series,index=['stat',p'])
将每个元组转换为一个包含2个值的序列,由于
out
已经有了索引,新的序列索引变成了列名+1:这比
out.apply(pd.Series)
快2倍。在我的例子中,元组是一对字符串(我有4000个),它比Siraj的答案快400倍……这比Siraj的答案要有效得多。
#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