按id创建n行 | Pandas

10
我有一个名为 df 的数据框,如下所示:
id lob addr addr2
a1 001 1234 0
a1 001 1233 0
a3 003 1221 0
a4 009 1234 0
我想要生成每个ID的n行(我们取4),其余列将为null/na/nan值。 因此,上表要转换为:
id lob addr addr2
a1 001 1234 0
a1 001 1233 0
a1 001 na na
a1 na na na
a3 003 1221 0
a3 na na na
a3 na na na
a3 na na na
a4 009 1234 0
a4 na na na
a4 na na na
a4 na na na
缺失

如何实现?在执行时,我将有500-700个ID,而n始终为70(因此每个ID应该有70行)。

我想创建一个循环,它会创建一行,按ID进行分组,查看是否小于70并重复该过程,但最终会执行许多不必要的操作。


2
id为1的第三行也应该是na。 - Rajesh
4个回答

6
以下是使用Counter计算每个ID需要多少额外行,并将新数据附加到末尾的解决方案:
from collections import Counter
id_count = Counter(df['id'])
# Create lists of each id repeated the number of times each is needed:
n = 4
id_values = [[i] * (n - id_count[i]) for i in id_count.keys()]
# Flatten to a single list:
id_values = [i for s in id_values for i in s]
# Create as new DataFrame and append to existing data:
new_data = pd.DataFrame({"id": id_values})
df = df.append(new_data).sort_values(by="id")

谢谢,我采用了这种方法,没有遇到任何问题。 - Harsha

5

您可以枚举一个 id 中的行,然后尝试使用 stack/unstackpivot

(df.assign(enum=df.groupby('id').cumcount())
   .query('enum <4')
   .set_index(['enum','id'])
   .unstack('id')
   .reindex(range(4))
   .stack('id',dropna=False)
   .sort_index(level='id')
   .reset_index('id')
)

嘿@Quang Hoang,感谢您的回复。您的答案出现了索引错误。我的示例实际上包含4列而不是3列(需求变更)。当我尝试使用您的代码时,我遇到了以下错误:IndexError:索引12超出了大小为12的轴0的范围。它在.stack('id',dropna=False)处失败。 - Harsha
@Harsha 代码可行。当我像这样创建df时 df = pd.DataFrame([s.split() for s in ["a1 001 1234 0", "a1 001 1233 0", "a3 003 1221 0", "a4 009 1234 0",]], columns=['id', 'lob', 'addr', 'addr2']) 我复制粘贴的数据来自问题。 - Chris Wesseling

0
你可以在Pandas中使用concat函数来优化运行时间,代码可能如下所示:
import pandas as pd
def replication(n, table):
        cols = [x in table.columns]
        empty_tab = table.copy()
        for x in cols:
            if x != 'ID':
                empty_tab[x] = np.nan
        for x in range(n):
                table = pd.concat([table, empty_tab.copy()], columns = cols) 
        return table

在这种情况下,第二个copy()并不是真正必要的。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接