以下问题是对此的简化:Iterating through lists within a pandas DataFrame
我有一个包含一列列表的DataFrame:
import numpy as np
import pandas as pd
col = [["A", "B", "C", "D"], ["E", "F"]]
d = {"col" : [["A", "B", "C", "D"], ["E", "F"]]}
df = pd.DataFrame(d)
print(df)
Out[2]:
col
0 [A, B, C, D]
1 [E, F]
对于每一行,我要遍历列表并在以下情况下进行选择:
生成的DataFrame应该如下所示:
col 0 1 2 3 4 5
0 [A, B, C, D] A B-A C-B D-C D np.nan
1 [E, F] E F-E F np.nan np.nan np.nan
要获得此结果,我尝试了一个嵌套的numpy.where
函数:
for i in range(7):
df[i] = pd.DataFrame(np.where(i == 0,
df["col"].apply(lambda x: x[0]),
np.where(i == df["col"].apply(len),
df["col"].apply(lambda x: x[-1]),
np.where((i > 0) & (i <= df["col"].apply(len) - 1),
df["col"].apply(lambda x: x[i]) + '-' + df["col"].apply(lambda x: x[i-1]),
np.nan
)
)
)
)
print(df)
这是我的问题:我得到一个IndexError: list index out of range
我想这与i
有关。
即使我发现i
的无效情况,整个嵌套的term项都不成立。 (我也用numpy.select
尝试过,但是得到了相同的结果。)
如果我将索引i
替换为1
,它会起作用(当然,它将给我错误的值,但我没有收到错误),因此它必须要做一些事情使用此索引,但我不知道如何解决该问题:
for i in range(7):
df[i] = pd.DataFrame(np.where(i == 0,
df["col"].apply(lambda x: x[0]),
np.where(i == df["col"].apply(len),
df["col"].apply(lambda x: x[-1]),
np.where((i > 0) & (i <= df["col"].apply(len) - 1),
df["col"].apply(lambda x: x[1]) + '-' + df["col"].apply(lambda x: x[1-1]),
np.nan
)
)
)
)
print(df)
col 0 1 2 3 4 5
0 [A, B, C, D] A B-A B-A B-A D np.nan
1 [E, F] E F-E F np.nan np.nan np.nan
您能想到解决此问题的方法还是获得我想要的DataFrame的另一种方法?非常感谢您的帮助。
答案 0 :(得分:1)
我会将逻辑编码为一个单独的函数:
from typing import List
def compute_event_transitions(L: List[str]) -> pd.Series:
if len(L) <= 1:
return pd.Series(L)
first = pd.Series(L[0])
last = pd.Series(L[-1])
s1 = pd.Series(L)
s2 = s1.shift(+1)
middle = (
pd.concat([s2, s1], axis='columns')
[1:] # The first element has no "from" transition
.apply(lambda s: "-".join(s.tolist()), axis='columns')
)
transitions = pd.concat([first, middle, last]).reset_index(drop=True)
return transitions
现在,您可以将此计算应用于数据框中的每个元素:
all_transitions = df['col'].apply(compute_event_transitions)
0 1 2 3 4 0 A A-B B-C C-D D 1 E E-F F NaN NaN
请注意,它的索引方式与原始数据帧相同,因此您可以将其缝合回列表列:
pd.concat([df, all_transitions], axis='columns')
col 0 1 2 3 4 0 [A, B, C, D] A A-B B-C C-D D 1 [E, F] E E-F F NaN NaN