Python 如何解包熊猫中的一系列元组?
有时我在使用Pandas时会得到一系列元组/列表。例如,执行group by并传递具有多个返回值的函数时,这种情况很常见: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
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