如何在Pandas中复制行?

lndjwyie  于 2022-12-16  发布在  其他
关注(0)|答案(8)|浏览(198)

我的Pandas Dataframe 看起来像这样:

Person  ID   ZipCode   Gender
0  12345   882  38182     Female
1  32917   271  88172     Male
2  18273   552  90291     Female

我想将每行复制3次,如下所示:

Person  ID   ZipCode   Gender
0  12345   882  38182     Female
0  12345   882  38182     Female
0  12345   882  38182     Female
1  32917   271  88172     Male
1  32917   271  88172     Male
1  32917   271  88172     Male
2  18273   552  90291     Female
2  18273   552  90291     Female
2  18273   552  90291     Female

当然,重新设置索引,使其为:

0
1
2
...

我尝试了以下解决方案:

pd.concat([df[:5]]*3, ignore_index=True)

以及:

df.reindex(np.repeat(df.index.values, df['ID']), method='ffill')

但都没用。

bhmjp9jg

bhmjp9jg1#

使用np.repeat

版本1:

尝试使用np.repeat

newdf = pd.DataFrame(np.repeat(df.values, 3, axis=0))
newdf.columns = df.columns
print(newdf)

上面的代码将输出:

Person   ID ZipCode  Gender
0  12345  882   38182  Female
1  12345  882   38182  Female
2  12345  882   38182  Female
3  32917  271   88172    Male
4  32917  271   88172    Male
5  32917  271   88172    Male
6  18273  552   90291  Female
7  18273  552   90291  Female
8  18273  552   90291  Female

np.repeat重复df3的值多次。
然后,我们添加列并指定new_df.columns = df.columns

版本2:

您还可以在第一行中指定列名,如下所示:

newdf = pd.DataFrame(np.repeat(df.values, 3, axis=0), columns=df.columns)
print(newdf)

以上代码还将输出:

Person   ID ZipCode  Gender
0  12345  882   38182  Female
1  12345  882   38182  Female
2  12345  882   38182  Female
3  32917  271   88172    Male
4  32917  271   88172    Male
5  32917  271   88172    Male
6  18273  552   90291  Female
7  18273  552   90291  Female
8  18273  552   90291  Female
beq87vna

beq87vna2#

这将重复索引并保留列,如op所示

iloc版本1

df.iloc[np.arange(len(df)).repeat(3)]

iloc版本2

df.iloc[np.arange(len(df) * 3) // 3]
dbf7pr2w

dbf7pr2w3#

使用concat

pd.concat([df]*3).sort_index()
Out[129]: 
   Person   ID  ZipCode  Gender
0   12345  882    38182  Female
0   12345  882    38182  Female
0   12345  882    38182  Female
1   32917  271    88172    Male
1   32917  271    88172    Male
1   32917  271    88172    Male
2   18273  552    90291  Female
2   18273  552    90291  Female
2   18273  552    90291  Female
wwtsj6pe

wwtsj6pe4#

我不知道为什么从来没有人提出过这一点,但是您可以很容易地将df.index.repeat.loc结合使用:

new_df = df.loc[df.index.repeat(3)]

输出:

>>> new_df
   Person   ID  ZipCode  Gender
0   12345  882    38182  Female
0   12345  882    38182  Female
0   12345  882    38182  Female
1   32917  271    88172    Male
1   32917  271    88172    Male
1   32917  271    88172    Male
2   18273  552    90291  Female
2   18273  552    90291  Female
2   18273  552    90291  Female
eivgtgni

eivgtgni5#

你可以这样做。

def do_things(df, n_times):
    ndf = df.append(pd.DataFrame({'name' : np.repeat(df.name.values, n_times) }))
    ndf = ndf.sort_values(by='name')
    ndf = ndf.reset_index(drop=True)
    return ndf

if __name__ == '__main__':
    df = pd.DataFrame({'name' : ['Peter', 'Quill', 'Jackson']}) 
    n_times = 3
    print do_things(df, n_times)

如果你解释清楚...

import pandas as pd
import numpy as np

n_times = 3
df = pd.DataFrame({'name' : ['Peter', 'Quill', 'Jackson']})
#       name
# 0    Peter
# 1    Quill
# 2  Jackson

#   Duplicating data.
df = df.append(pd.DataFrame({'name' : np.repeat(df.name.values, n_times) }))
#       name
# 0    Peter
# 1    Quill
# 2  Jackson
# 0    Peter
# 1    Peter
# 2    Peter
# 3    Quill
# 4    Quill
# 5    Quill
# 6  Jackson
# 7  Jackson
# 8  Jackson

#   The DataFrame is sorted by 'name' column.
df = df.sort_values(by=['name'])
#       name
# 2  Jackson
# 6  Jackson
# 7  Jackson
# 8  Jackson
# 0    Peter
# 0    Peter
# 1    Peter
# 2    Peter
# 1    Quill
# 3    Quill
# 4    Quill
# 5    Quill

#   Reseting the index.
#   You can play with drop=True and drop=False, as parameter of `reset_index()`
df = df.reset_index()
#     index     name
# 0       2  Jackson
# 1       6  Jackson
# 2       7  Jackson
# 3       8  Jackson
# 4       0    Peter
# 5       0    Peter
# 6       1    Peter
# 7       2    Peter
# 8       1    Quill
# 9       3    Quill
# 10      4    Quill
# 11      5    Quill
kxe2p93d

kxe2p93d6#

您可以尝试以下代码:

df = df.iloc[df.index.repeat(3),:].reset_index()

df.index.repeat(3)将创建一个列表,其中每个索引值将重复3次,并且df.iloc[df.index.repeat(3),:]将帮助生成一个 Dataframe ,其中的行与该列表返回的行完全相同。

tsm1rwdh

tsm1rwdh7#

如果您需要索引重复(例如,对于多索引),并且还需要基于列中的值来计算重复次数,您可以执行以下操作:

someDF["RepeatIndex"] = someDF["RepeatBasis"].fillna(value=0).apply(lambda x: list(range(int(x))) if x > 0 else [])
superDF = someDF.explode("RepeatIndex").dropna(subset="RepeatIndex")

这将提供一个DataFrame,其中每条记录都重复,无论“RepeatBasis”列中指示的次数是多少。DataFrame还将获得一个“RepeatIndex”列,您可以将该列与现有索引合并成多索引,从而保持索引唯一性。
如果有人想知道为什么你要做这样的事情,在我的例子中,当我得到的数据中的频率已经被总结,无论出于什么原因,我需要处理奇异观察。

ar5n3qh5

ar5n3qh58#

这个问题还没有足够的答案!下面是一些仍然缺少的允许链接的方法:)

# SQL-style cross-join
# (one line and counts replicas)
(
    data
    .join(pd.DataFrame(range(3), columns=["replica"]), how="cross")
    .drop(columns="replica")  # remove if you want to count replicas
)
# DataFrame.apply + Series.repeat
# (most readable, but potentially slow)
(
    data
    .apply(lambda x: x.repeat(3))
    .reset_index(drop=True)
)
# DataFrame.explode
# (fun to have explosions in your code)
(
    data
    .assign(replica=lambda df: [[x for x in range(3)]] * len(df))
    .explode("replica", ignore_index=True)
    .drop(columns="replica")  # or keep if you want to know which copy it is
)

编辑:更重要的是,如果需要计算副本 * 并且 * 每行具有动态副本计数,则使用explode非常有用。例如,如果您具有包含开始日期和结束日期的每个客户的使用情况数据,则可以使用上述方法将数据转换为每个客户的每月使用情况数据。)
当然,下面是创建测试数据的代码片段:

data = pd.DataFrame([
        [12345, 882, 38182, "Female"],
        [32917, 271, 88172, "Male"],
        [18273, 552, 90291, "Female"],
    ],
    columns=["Person", "ID", "ZipCode", "Gender"]
)

相关问题