如果数据框看起来像:
Store,Dept,Date,Weekly_Sales,IsHoliday
1,1,2010-02-05,24924.5,FALSE
1,1,2010-02-12,46039.49,TRUE
1,1,2010-02-19,41595.55,FALSE
1,1,2010-02-26,19403.54,FALSE
1,1,2010-03-05,21827.9,FALSE
1,1,2010-03-12,21043.39,FALSE
1,1,2010-03-19,22136.64,FALSE
1,1,2010-03-26,26229.21,FALSE
1,1,2010-04-02,57258.43,FALSE
我想复制
IsHoliday
等于 TRUE 的行,我可以这样做:
is_hol = df['IsHoliday'] == True
df_try = df[is_hol]
df=df.append(df_try*10)
但是有没有更好的方法来做到这一点,因为我需要复制假期行 5 次,如果使用上述方式,我必须追加 5 次。
您可以将
df_try
放入列表中,然后按照您的想法进行操作:
>>> df.append([df_try]*5,ignore_index=True)
Store Dept Date Weekly_Sales IsHoliday
0 1 1 2010-02-05 24924.50 False
1 1 1 2010-02-12 46039.49 True
2 1 1 2010-02-19 41595.55 False
3 1 1 2010-02-26 19403.54 False
4 1 1 2010-03-05 21827.90 False
5 1 1 2010-03-12 21043.39 False
6 1 1 2010-03-19 22136.64 False
7 1 1 2010-03-26 26229.21 False
8 1 1 2010-04-02 57258.43 False
9 1 1 2010-02-12 46039.49 True
10 1 1 2010-02-12 46039.49 True
11 1 1 2010-02-12 46039.49 True
12 1 1 2010-02-12 46039.49 True
13 1 1 2010-02-12 46039.49 True
另一种方法是使用 concat() 函数:
import pandas as pd
In [603]: df = pd.DataFrame({'col1':list("abc"),'col2':range(3)},index = range(3))
In [604]: df
Out[604]:
col1 col2
0 a 0
1 b 1
2 c 2
In [605]: pd.concat([df]*3, ignore_index=True) # Ignores the index
Out[605]:
col1 col2
0 a 0
1 b 1
2 c 2
3 a 0
4 b 1
5 c 2
6 a 0
7 b 1
8 c 2
In [606]: pd.concat([df]*3)
Out[606]:
col1 col2
0 a 0
1 b 1
2 c 2
0 a 0
1 b 1
2 c 2
0 a 0
1 b 1
2 c 2
这是一个老问题,但由于它仍然出现在我的谷歌搜索结果的顶部,所以这是另一种方法。
import pandas as pd
import numpy as np
df = pd.DataFrame({'col1':list("abc"),'col2':range(3)},index = range(3))
假设您要复制 col1="b" 的行。
reps = [3 if val=="b" else 1 for val in df.col1]
df.loc[np.repeat(df.index.values, reps)]
您可以将列表解释中的
3 if val=="b" else 1
替换为另一个函数,该函数可以返回 3 if val=="b" 或 4 if val=="c" 等等,所以它非常灵活。
在 Pandas 中附加和连接通常很慢,所以我建议只创建一个新的行列表并将其转换为数据帧(除非附加单行或连接几个数据帧)。
import pandas as pd
df = pd.DataFrame([
[1,1,'2010-02-05',24924.5,False],
[1,1,'2010-02-12',46039.49,True],
[1,1,'2010-02-19',41595.55,False],
[1,1,'2010-02-26',19403.54,False],
[1,1,'2010-03-05',21827.9,False],
[1,1,'2010-03-12',21043.39,False],
[1,1,'2010-03-19',22136.64,False],
[1,1,'2010-03-26',26229.21,False],
[1,1,'2010-04-02',57258.43,False]
], columns=['Store','Dept','Date','Weekly_Sales','IsHoliday'])
temp_df = []
for row in df.itertuples(index=False):
if row.IsHoliday:
temp_df.extend([list(row)]*5)
else:
temp_df.append(list(row))
df = pd.DataFrame(temp_df, columns=df.columns)
您只需一行即可完成:
df.append([df[df['IsHoliday'] == True]] * 5, ignore_index=True)
或
df.append([df[df['IsHoliday']]] * 5, ignore_index=True)
append()
的另一种替代方法是首先用条目列表替换列的值,然后使用explode()
(可以使用ignore_index=True
,也可以不使用,具体取决于您想要的):
df['IsHoliday'] = df['IsHoliday'].apply(lambda x: 5*[x] if (x == True) else x)
df.explode('IsHoliday', ignore_index=True)
这个的好处是,您已经可以使用
apply()
调用中的列表来构建列中具有修改值的行副本,以防您以后想这样做...
这是使用 numpy.tile() 的另一种方法
df = pd.DataFrame([
[1,1,'2010-02-05',24924.5,False],
[1,1,'2010-02-12',46039.49,True],
[1,1,'2010-02-19',41595.55,False],
[1,1,'2010-02-26',19403.54,False],
[1,1,'2010-03-05',21827.9,False],
[1,1,'2010-03-12',21043.39,False],
[1,1,'2010-03-19',22136.64,False],
[1,1,'2010-03-26',26229.21,False],
[1,1,'2010-04-02',57258.43,False]
], columns=['Store','Dept','Date','Weekly_Sales','IsHoliday'])
df= df.loc[df['IsHoliday']==True]
%%timeit
pd.concat([df]*5,axis=0)
每次循环 801 µs ± 29.4 µs(7 次运行的平均值 ± 标准偏差,每次 1000 个循环)
%%timeit
pd.DataFrame(np.tile(df.to_numpy(), (5,1)), columns = df.columns)
每个循环 261 µs ± 16.3 µs(7 次运行的平均值 ± 标准偏差,每次 1000 个循环)