Как распаковать серию кортежей в 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 с двумя столбцами?
Связанный вопрос заключается в том, как я могу распаковать эту структуру или результирующий фреймворк в два объекта Series/array. Это почти работает:
t, p = zip(*out)
но он t
равен
(array(1.3066417475999257),
array(0.08011333825171714),
array(1.557843291126335),
array(0.267999459641651))
и нужно сделать дополнительный шаг, чтобы сжать его.
Ответы
Ответ 1
может быть, это самое страшное (большинство pythonic, я думаю):
out.apply(pd.Series)
если вы хотите переименовать столбцы в нечто более значимое, чем:
out.columns=['Kstats','Pvalue']
если вы не хотите использовать имя по умолчанию для индекса:
out.index.name=None
Ответ 2
может быть:
>>> 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]
Ответ 3
Я считаю, что вы этого хотите:
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
Ответ 4
Я столкнулся с подобной проблемой. То, что я нашел, 2 способа его решения - это точно ответ @CT ZHU и @Siraj S.
Вот моя дополнительная информация, которая вам может быть интересна:
Я сравнил 2 пути и нашел способ @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 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 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: Прошу простить мой уродливый код.