2016-12-06 2 views
3

Я застрял в тупике, и я использую какой-то код, который явно не-панды для того, что должно быть очень простой задачей в Pandas. Я уверен, что есть лучший способ.Pandas для дублирования одной строки, чтобы заполнить DataFrame

У меня есть DataFrame, что я буду извлекать одну строку из и создать новый DataFrame так:

>>> sampledata 
float_col int_col str_col r v new_coltest  eddd 
0  0.1  1  a 5 1.0   0.1 -0.539783 
1  0.2  2  b 5 NaN   0.2 -1.394550 
2  0.2  6 None 5 NaN   0.2 0.290157 
3  10.1  8  c 5 NaN   10.1 -1.799373 
4  NaN  -1  a 5 NaN   NaN 0.694682 
>>> newsampledata = sampledata[(sampledata.new_coltest == 0.1) & (sampledata.float_col == 0.1)] 
>>> newsampledata 
float_col int_col str_col r v new_coltest  eddd 
0  0.1  1  a 5 1.0   0.1 -0.539783 

То, что я хотел бы сделать, это скопировать этот одну строку в «newsampledata» п раз, где n - известное целое число. В идеале конечный DataFrame с n строками перезаписывает однострочные «newsampledata», но это никоим образом не критично.

В настоящее время я использую цикл for для выполнения pd.concat n-1 раз, чтобы получить заполнение DataFrame, но это не так быстро из-за того, что работает concat. Я также пробовал использовать такую ​​же тактику, используя append, и это немного медленнее, чем concat.

Я видел несколько других вопросов, заданных по поводу похожих предметов, но многие до сих пор не видели этот точный вопрос. Кроме того, меня отвлекают от карты/заявки из-за проблем с производительностью, но если вы видели хорошую производительность в этом методе, пожалуйста, дайте мне знать, и я тоже попробую.

ТИА

ответ

4

Вы можете использовать DataFrame конструктор:

N = 10 
df =pd.DataFrame(newsampledata.values.tolist(),index=np.arange(N),columns=sampledata.columns) 
print (df) 
    float_col int_col str_col r v new_coltest  eddd 
0  0.1  1  a 5 1.0   0.1 -0.539783 
1  0.1  1  a 5 1.0   0.1 -0.539783 
2  0.1  1  a 5 1.0   0.1 -0.539783 
3  0.1  1  a 5 1.0   0.1 -0.539783 
4  0.1  1  a 5 1.0   0.1 -0.539783 
5  0.1  1  a 5 1.0   0.1 -0.539783 
6  0.1  1  a 5 1.0   0.1 -0.539783 
7  0.1  1  a 5 1.0   0.1 -0.539783 
8  0.1  1  a 5 1.0   0.1 -0.539783 
9  0.1  1  a 5 1.0   0.1 -0.539783 

print (df.dtypes) 
float_col  float64 
int_col   int64 
str_col   object 
r    int64 
v    float64 
new_coltest float64 
eddd   float64 
dtype: object 

Timings:

Мал DataFrame быстрее sample и reindex методы, в большом методе DataFrame конструктора.

N = 1000 
In [88]: %timeit (pd.DataFrame(newsampledata.values.tolist(), index=np.arange(N), columns=sampledata.columns)) 
1000 loops, best of 3: 745 µs per loop 

In [89]: %timeit (newsampledata.sample(N, replace=True).reset_index(drop=True)) 
The slowest run took 4.88 times longer than the fastest. This could mean that an intermediate result is being cached. 
1000 loops, best of 3: 470 µs per loop 

In [90]: %timeit (newsampledata.reindex(newsampledata.index.repeat(N)).reset_index(drop=True)) 
1000 loops, best of 3: 476 µs per loop 

N = 10000 
In [92]: %timeit (pd.DataFrame(newsampledata.values.tolist(), index=np.arange(N), columns=sampledata.columns)) 
1000 loops, best of 3: 946 µs per loop 

In [93]: %timeit (newsampledata.sample(N, replace=True).reset_index(drop=True)) 
1000 loops, best of 3: 775 µs per loop 

In [94]: %timeit (newsampledata.reindex(newsampledata.index.repeat(N)).reset_index(drop=True)) 
1000 loops, best of 3: 827 µs per loop 

N = 100000 
In [97]: %timeit (pd.DataFrame(newsampledata.values.tolist(), index=np.arange(N), columns=sampledata.columns)) 
The slowest run took 12.98 times longer than the fastest. This could mean that an intermediate result is being cached. 
100 loops, best of 3: 6.93 ms per loop 

In [98]: %timeit (newsampledata.sample(N, replace=True).reset_index(drop=True)) 
100 loops, best of 3: 7.07 ms per loop 

In [99]: %timeit (newsampledata.reindex(newsampledata.index.repeat(N)).reset_index(drop=True)) 
100 loops, best of 3: 7.87 ms per loop 

N = 10000000 
In [83]: %timeit (pd.DataFrame(newsampledata.values.tolist(), index=np.arange(N), columns=sampledata.columns)) 
1 loop, best of 3: 589 ms per loop 

In [84]: %timeit (newsampledata.sample(N, replace=True).reset_index(drop=True)) 
1 loop, best of 3: 757 ms per loop 

In [85]: %timeit (newsampledata.reindex(newsampledata.index.repeat(N)).reset_index(drop=True)) 
1 loop, best of 3: 731 ms per loop 
+0

Хорошее решение, кажется, работа без проблем, и я согласен, это быстрее. Не знал, как настроить индекс, придется помнить об этом! – rajan

+0

В предыдущей версии у вас была numpy-версия с недостатком, что dtypes, преобразованный в объект. Как это решение сравнивается с производительностью при возвращении к исходным типам данных? Может быть, numpy еще быстрее;) – Quickbeam2k1

+1

@ Quickbeam2k1 - Я пробовал. – jezrael

6

Я полагаю, вы могли бы просто sample это с заменой

newsampledata.sample(n, replace=True).reset_index(drop=True) 

или reindex

newsampledata.reindex(newsampledata.index.repeat(n)).reset_index(drop=True) 
2

Я думаю, что вы можете использовать CONCAT без использования для цикла в явном виде.

df = pd.DataFrame({'a':[1], 'b':[.1]}) 
repetitions = 4 
res = pd.concat([df]*repetitions) 
print(res) 

Выход

a b 
0 1 0.1 
0 1 0.1 
0 1 0.1 
0 1 0.1 

Так что на моем образце кадра, это действительно быстрее, чем для циклов с коэффициентом примерно 5. Тем не менее, я бы ожидать различные решения, не используя CONCAT быть значительно Быстрее.

Чтобы показать хо медленный CONCAT есть некоторый ориентир по сравнению с одним из решений jezrael в enter image description here

+0

concat очень медленно. Однострочный фрейм занимает 1,5 с для n = 10 000 –

+0

Вы правы. Однако это решение, по крайней мере, быстрее, чем использование цикла for напрямую. – Quickbeam2k1

+0

выполнил некоторые тесты против решения jezraels, чтобы показать, насколько медленным является concat – Quickbeam2k1

1

один из А bajillion способов сделать это

pd.concat([df.query('new_coltest == 0.1 & float_col == 0.1')] * 4) 

enter image description here

Смежные вопросы