我必须在循环中逐列构建我的DataFrame。每一列的长度不同。
我从一个空的DataFrame开始,但是我已经知道了列名:
import pandas as pd
df = pd.DataFrame(columns=['g1','g2'])
我的列数据是从另一个DataFrame作为Series提取的。让我们在这里创建一些虚构的:
s1 = pd.Series(index=[1,2],data=[10,11],name='g1')
s2 = pd.Series(index=[3,4,5],data=[12,13,14],name='g2')
# etc.
请注意,两个系列具有不同的索引值和不同的长度(不是所有的索引值都不同,有些可能重叠)。现在我想进入循环,并在每次迭代时向DataFrame添加一个新列。在循环结束时,我的DataFrame应该是这样的:
Index g1 g2
0 10 12
1 11 13
2 NaN 14
换句话说:
- 索引扩展到覆盖最大的列并复位为0。n-1,其中n是最大值。所有列的长度
- 每个系列作为一个新列追加,其名称与原来已知的列名称相同
- 缺少的元素是NaN
与name
和DataFrame
:
df = pd.DataFrame({s.name: s.reset_index(drop=True) for s in [s1, s2]})
输出:
print(df)
g1 g2
0 10.0 12
1 11.0 13
2 NaN 14
使用concat
和Series.reset_index
,参数drop=True
作为默认索引:
L = [s1, s2]
df = pd.concat([s.reset_index(drop=True) for s in L], axis=1)
print (df)
g1 g2
0 10.0 12
1 11.0 13
2 NaN 14
循环解决方案:
L = [s1, s2]
for s in L:
s1 = s.reset_index(drop=True)
df = df.reindex(s1.index)
df[s1.name] = s1
print (df)
g1 g2
0 10.0 12
1 11.0 13
2 NaN 14
基于@Timeless的答案,如果您想在适当的位置更新原始DataFrame,您可以使用:
l = [s1, s2]
tmp = pd.DataFrame({s.name: s.reset_index(drop=True) for s in l})
df[list(tmp)] = tmp
print(df)
或者,作为一行代码:
df[list(tmp)] = (tmp:=pd.DataFrame({s.name: s.reset_index(drop=True) for s in [s1, s2]}))
print(df)
输出:
g1 g2
0 10.0 12
1 11.0 13
2 NaN 14
以下是我找到的两个解决方案:
- 感谢@Timeless。第一种解决方案在循环中构建一个序列列表,然后在末尾使用字典构造一个DataFrame。
series_list = []
for i in col_names:
series_list.append(series)
df = pd.DataFrame({s.name: s.reset_index(drop=True) for s in series_list})
- 感谢
jezrael
,他有使用concat
而不是merge
的洞察力,这是我最初试图使用的。在本例中,我们从一个空的DataFrame开始,然后在每次迭代中添加一个新列。在添加序列之前,我们重置了序列的索引。使用concat
而不是仅仅将序列分配给列的优点是,concat
会根据需要自动扩大DataFrame
df = pd.DataFrame()
s = # get new column at each iteration
for i in col_names:
df = pd.concat([df,s.reset_index(drop=True).rename(i)],axis=1)