перетасовка / перестановка фрейма данных в панд



какой простой и эффективный способ перетасовать фрейм данных в панд, по строкам или по столбцам? Т. е. как написать функцию shuffle(df, n, axis=0) это занимает фрейм данных, ряд перетасовок n, и ось (axis=0 это строки axis=1 is columns) и возвращает копию кадра данных, который был перетасован n раза.



Edit: ключ должен сделать это, не разрушая метки строк / столбцов фрейма данных. Если вы просто перемешать df.index что теряет все, что информация. Я хочу, чтобы в результате df быть таким же, как оригинал, за исключением того, что порядок строк или порядок столбцов отличается.



Edit2: мой вопрос был неясен. Когда я говорю перетасовать строки, я имею в виду перетасовать каждую строку независимо. Так что если у вас есть два столбца a и b, Я хочу, чтобы каждая строка перетасовывалась сама по себе, чтобы у вас не было одинаковых ассоциаций между a и b как вы делаете, если вы просто переупорядочить каждую строку в целом. Что-то например:



for 1...n:
for each col in df: shuffle column
return new_df


но, надеюсь, более эффективным, чем наивный цикл. Это не работает для меня:



def shuffle(df, n, axis=0):
shuffled_df = df.copy()
for k in range(n):
shuffled_df.apply(np.random.shuffle(shuffled_df.values),axis=axis)
return shuffled_df

df = pandas.DataFrame({'A':range(10), 'B':range(10)})
shuffle(df, 5)
630   11  

11 ответов:

In [16]: def shuffle(df, n=1, axis=0):     
    ...:     df = df.copy()
    ...:     for _ in range(n):
    ...:         df.apply(np.random.shuffle, axis=axis)
    ...:     return df
    ...:     

In [17]: df = pd.DataFrame({'A':range(10), 'B':range(10)})

In [18]: shuffle(df)

In [19]: df
Out[19]: 
   A  B
0  8  5
1  1  7
2  7  3
3  6  2
4  3  4
5  0  1
6  9  0
7  4  6
8  2  8
9  5  9

использовать библиотеки numpy это random.permuation функция:

In [1]: df = pd.DataFrame({'A':range(10), 'B':range(10)})

In [2]: df
Out[2]:
   A  B
0  0  0
1  1  1
2  2  2
3  3  3
4  4  4
5  5  5
6  6  6
7  7  7
8  8  8
9  9  9


In [3]: df.reindex(np.random.permutation(df.index))
Out[3]:
   A  B
0  0  0
5  5  5
6  6  6
3  3  3
8  8  8
7  7  7
9  9  9
1  1  1
2  2  2
4  4  4

выборка рандомизируется, поэтому просто попробуйте весь фрейм данных.

df.sample(frac=1)

можно использовать sklearn.utils.shuffle() (требует sklearn 0.16.1 или выше для поддержки фреймов данных Pandas):

# Generate data
import pandas as pd
df = pd.DataFrame({'A':range(5), 'B':range(5)})
print('df: {0}'.format(df))

# Shuffle Pandas data frame
import sklearn.utils
df = sklearn.utils.shuffle(df)
print('\n\ndf: {0}'.format(df))

выходы:

df:    A  B
0  0  0
1  1  1
2  2  2
3  3  3
4  4  4


df:    A  B
1  1  1
0  0  0
3  3  3
4  4  4
2  2  2

затем вы можете использовать df.reset_index() чтобы сбросить столбец индекса, если нужно быть:

df = df.reset_index(drop=True)
print('\n\ndf: {0}'.format(df)

выходы:

df:    A  B
0  1  1
1  0  0
2  4  4
3  2  2
4  3  3

из документов используйте sample():

In [79]: s = pd.Series([0,1,2,3,4,5])

# When no arguments are passed, returns 1 row.
In [80]: s.sample()
Out[80]: 
0    0
dtype: int64

# One may specify either a number of rows:
In [81]: s.sample(n=3)
Out[81]: 
5    5
2    2
4    4
dtype: int64

# Or a fraction of the rows:
In [82]: s.sample(frac=0.5)
Out[82]: 
5    5
4    4
1    1
dtype: int64

я прибегнул к адаптации @root 's ответ немного и с использованием необработанных значений непосредственно. Конечно, это означает, что вы теряете возможность делать причудливую индексацию, но она отлично работает для простого перетасовки данных.

In [1]: import numpy

In [2]: import pandas

In [3]: df = pandas.DataFrame({"A": range(10), "B": range(10)})    

In [4]: %timeit df.apply(numpy.random.shuffle, axis=0)
1000 loops, best of 3: 406 µs per loop

In [5]: %%timeit
   ...: for view in numpy.rollaxis(df.values, 1):
   ...:     numpy.random.shuffle(view)
   ...: 
10000 loops, best of 3: 22.8 µs per loop

In [6]: %timeit df.apply(numpy.random.shuffle, axis=1)
1000 loops, best of 3: 746 µs per loop

In [7]: %%timeit                                      
for view in numpy.rollaxis(df.values, 0):
    numpy.random.shuffle(view)
   ...: 
10000 loops, best of 3: 23.4 µs per loop

отметим, что numpy.rollaxis приводит указанную ось к первому измерению, а затем давайте переберем массивы с оставшимися измерениями, т. е. если мы хотим перетасовать первое измерение (столбцы), нам нужно свернуть второе измерение на фронт, чтобы мы применяем перетасовку к представлениям над первым измерением.

In [8]: numpy.rollaxis(df, 0).shape
Out[8]: (10, 2) # we can iterate over 10 arrays with shape (2,) (rows)

In [9]: numpy.rollaxis(df, 1).shape
Out[9]: (2, 10) # we can iterate over 2 arrays with shape (10,) (columns)

ваша конечная функция затем использует трюк, чтобы привести результат в соответствие с ожиданием применения функции к оси:

def shuffle(df, n=1, axis=0):     
    df = df.copy()
    axis = int(not axis) # pandas.DataFrame is always 2D
    for _ in range(n):
        for view in numpy.rollaxis(df.values, axis):
            numpy.random.shuffle(view)
    return df

Это может быть более полезно, когда вы хотите, чтобы ваш индекс перетасовали.

def shuffle(df):
    index = list(df.index)
    random.shuffle(index)
    df = df.ix[index]
    df.reset_index()
    return df

он выбирает новый df с помощью нового индекса, а затем сбросить их.

Если вы хотите перетасовать только один столбец (не Индекс) фрейма данных с большим количеством столбцов:

df ['column_name'] = numpy.случайность.перестановка(ДФ.column_name)

простое решение в панд является использование sample метод независимо от каждого столбца. Используйте apply для итерации по каждому столбцу:

df = pd.DataFrame({'a':[1,2,3,4,5,6], 'b':[1,2,3,4,5,6]})
df

   a  b
0  1  1
1  2  2
2  3  3
3  4  4
4  5  5
5  6  6

df.apply(lambda x: x.sample(frac=1).values)

   a  b
0  4  2
1  1  6
2  6  5
3  5  3
4  2  4
5  3  1

вы должны использовать .value так что вы возвращаете массив numpy, а не серию, иначе возвращенная серия будет выровнена по исходному фрейму данных, не меняя ничего:

df.apply(lambda x: x.sample(frac=1))

   a  b
0  1  1
1  2  2
2  3  3
3  4  4
4  5  5
5  6  6

вот работа, которую я нашел, если вы хотите только перетасовать подмножество фрейма данных:

shuffle_to_index = 20
df = pd.concat([df.iloc[np.random.permutation(range(shuffle_to_index))], df.iloc[shuffle_to_index:]])

Я знаю, что вопрос для pandas df но в случае, если перетасовка происходит по строке (порядок столбцов изменен, порядок строк не изменился), то имена столбцов больше не имеют значения, и было бы интересно использовать np.array, а затем np.apply_along_axis() будет то, что вы ищете.

если это приемлемо, то это было бы полезно, обратите внимание, что легко переключить ось, вдоль которой данные перемешиваются.

если вы panda фрейм данных называется df, может быть, вы может:

  1. получить значения фрейма данных с values = df.values,
  2. создать np.array С values
  3. примените метод, показанный ниже, чтобы перетасовать np.array по строке или столбцу
  4. воссоздать новую (перетасованную) панду df из перетасованной np.array

исходный массив

a = np.array([[10, 11, 12], [20, 21, 22], [30, 31, 32],[40, 41, 42]])
print(a)
[[10 11 12]
 [20 21 22]
 [30 31 32]
 [40 41 42]]

сохранить порядок строк, перемешать столбцы в каждой строке

print(np.apply_along_axis(np.random.permutation, 1, a))
[[11 12 10]
 [22 21 20]
 [31 30 32]
 [40 41 42]]

держите порядок Колумб, перемешайте строки внутри каждого колонка

print(np.apply_along_axis(np.random.permutation, 0, a))
[[40 41 32]
 [20 31 42]
 [10 11 12]
 [30 21 22]]

исходный массив не изменился

print(a)
[[10 11 12]
 [20 21 22]
 [30 31 32]
 [40 41 42]]

Comments

    Ничего не найдено.