Подтвердить что ты не робот

Разделение кадра данных на несколько фреймов данных

У меня очень большой фреймворк (около 1 миллиона строк) с данными из эксперимента (60 респондентов). Я хотел бы разделить фрейм данных на 60 фреймов данных (кадр данных для каждого участника).

В фрейме данных (называемом = data) существует переменная с именем 'name', которая является уникальным кодом для каждого участника.

Я пробовал следующее, но ничего не происходит (или не останавливается в течение часа). То, что я намереваюсь сделать, - разделить данные (данные) на более мелкие фреймы данных и добавить их в список (datalist):

import pandas as pd

def splitframe(data, name='name'):

    n = data[name][0]

    df = pd.DataFrame(columns=data.columns)

    datalist = []

    for i in range(len(data)):
        if data[name][i] == n:
            df = df.append(data.iloc[i])
        else:
            datalist.append(df)
            df = pd.DataFrame(columns=data.columns)
            n = data[name][i]
            df = df.append(data.iloc[i])

    return datalist

Я не получаю сообщение об ошибке, script просто запускается навсегда!

Есть ли разумный способ сделать это?

4b9b3361

Ответ 1

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

Тем не менее, я думаю, что в основном ваш подход немного расточителен, так как у вас уже есть фрейм данных, так зачем создавать новый для каждого из этих пользователей?

Я бы отсортировал фрейм данных по столбцу 'name', установил бы индекс таким, и при необходимости не удалял столбец.

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

Так:

# sort the dataframe
df.sort(columns=['name'], inplace=True)
# set the index to be this and don't drop
df.set_index(keys=['name'], drop=False,inplace=True)
# get a list of names
names=df['name'].unique().tolist()
# now we can perform a lookup on a 'view' of the dataframe
joe = df.loc[df.name=='joe']
# now you can query all 'joes'

РЕДАКТИРОВАТЬ

sort устарела, вам нужно использовать sort_values сейчас:

# sort the dataframe
df.sort_values(by='name', axis=1, inplace=True)
# set the index to be this and don't drop
df.set_index(keys=['name'], drop=False,inplace=True)
# get a list of names
names=df['name'].unique().tolist()
# now we can perform a lookup on a 'view' of the dataframe
joe = df.loc[df.name=='joe']
# now you can query all 'joes'

Ответ 2

Могу ли я спросить, почему бы просто не сделать это, отрезав фрейм данных. Что-то вроде

#create some data with Names column
data = pd.DataFrame({'Names': ['Joe', 'John', 'Jasper', 'Jez'] *4, 'Ob1' : np.random.rand(16), 'Ob2' : np.random.rand(16)})

#create unique list of names
UniqueNames = data.Names.unique()

#create a data frame dictionary to store your data frames
DataFrameDict = {elem : pd.DataFrame for elem in UniqueNames}

for key in DataFrameDict.keys():
    DataFrameDict[key] = data[:][data.Names == key]

Привет, у вас есть словарь данных, так же, как (я думаю), вы хотите их. Нужно получить доступ к одному? Просто введите

DataFrameDict['Joe']

Надеюсь, что поможет

Ответ 3

Вы можете преобразовать объект groupby в tuples а затем в dict:

df = pd.DataFrame({'Name':list('aabbef'),
                   'A':[4,5,4,5,5,4],
                   'B':[7,8,9,4,2,3],
                   'C':[1,3,5,7,1,0]}, columns = ['Name','A','B','C'])

print (df)
  Name  A  B  C
0    a  4  7  1
1    a  5  8  3
2    b  4  9  5
3    b  5  4  7
4    e  5  2  1
5    f  4  3  0

d = dict(tuple(df.groupby('Name')))
print (d)
{'b':   Name  A  B  C
2    b  4  9  5
3    b  5  4  7, 'e':   Name  A  B  C
4    e  5  2  1, 'a':   Name  A  B  C
0    a  4  7  1
1    a  5  8  3, 'f':   Name  A  B  C
5    f  4  3  0}

print (d['a'])
  Name  A  B  C
0    a  4  7  1
1    a  5  8  3

Не рекомендуется, но возможно создание DataFrames по группам:

for i, g in df.groupby('Name'):
    globals()['df_' + str(i)] =  g

print (df_a)
  Name  A  B  C
0    a  4  7  1
1    a  5  8  3

Ответ 4

Groupby может помочь вам:

grouped = data.groupby(['name'])

Затем вы можете работать с каждой группой, как с кадром данных для каждого участника. И методы объекта DataFrameGroupBy, такие как (применить, преобразовать, агрегировать, заголовок, первый, последний), возвращают объект DataFrame.

Или вы можете составить список из grouped и получить весь DataFrame по индексу:

l_grouped = list(grouped)

l_grouped[0][1] - DataFrame для первой группы с именем.

Ответ 5

Легко:

[v for k, v in df.groupby('name')]

Ответ 6

В дополнение к ответу Гусева Славы, вы можете использовать группы groupby:

{key: df.loc[value] for key, value in df.groupby("name").groups.items()}

Это даст словарь с ключами, которые вы сгруппировали, указав на соответствующие разделы. Преимущество заключается в том, что ключи сохраняются и не исчезают в индексе списка.

Ответ 7

In [28]: df = DataFrame(np.random.randn(1000000,10))

In [29]: df
Out[29]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 1000000 entries, 0 to 999999
Data columns (total 10 columns):
0    1000000  non-null values
1    1000000  non-null values
2    1000000  non-null values
3    1000000  non-null values
4    1000000  non-null values
5    1000000  non-null values
6    1000000  non-null values
7    1000000  non-null values
8    1000000  non-null values
9    1000000  non-null values
dtypes: float64(10)

In [30]: frames = [ df.iloc[i*60:min((i+1)*60,len(df))] for i in xrange(int(len(df)/60.) + 1) ]

In [31]: %timeit [ df.iloc[i*60:min((i+1)*60,len(df))] for i in xrange(int(len(df)/60.) + 1) ]
1 loops, best of 3: 849 ms per loop

In [32]: len(frames)
Out[32]: 16667

Здесь групповой способ (и вы можете сделать произвольное применение, а не сумму)

In [9]: g = df.groupby(lambda x: x/60)

In [8]: g.sum()    

Out[8]: 
<class 'pandas.core.frame.DataFrame'>
Int64Index: 16667 entries, 0 to 16666
Data columns (total 10 columns):
0    16667  non-null values
1    16667  non-null values
2    16667  non-null values
3    16667  non-null values
4    16667  non-null values
5    16667  non-null values
6    16667  non-null values
7    16667  non-null values
8    16667  non-null values
9    16667  non-null values
dtypes: float64(10)

Сумма cythonized, почему это так быстро

In [10]: %timeit g.sum()
10 loops, best of 3: 27.5 ms per loop

In [11]: %timeit df.groupby(lambda x: x/60)
1 loops, best of 3: 231 ms per loop

Ответ 8

Метод, основанный на понимании списка и groupby - который сохраняет весь разделенный фрейм данных в переменной списка и доступен с помощью индекса.

пример

ans = [pd.DataFrame(y) for x, y in DF.groupby('column_name', as_index=False)]

ans[0]
ans[0].column_name

Ответ 9

Вы можете использовать команду groupby, если у вас уже есть метки для ваших данных.

 out_list = [group[1] for group in in_series.groupby(label_series.values)]

Вот подробный пример:

Допустим, мы хотим разделить серию pd, используя некоторые метки, в список чанков. Например, in_series:

2019-07-01 08:00:00   -0.10
2019-07-01 08:02:00    1.16
2019-07-01 08:04:00    0.69
2019-07-01 08:06:00   -0.81
2019-07-01 08:08:00   -0.64
Length: 5, dtype: float64

И соответствующий ему label_series:

2019-07-01 08:00:00   1
2019-07-01 08:02:00   1
2019-07-01 08:04:00   2
2019-07-01 08:06:00   2
2019-07-01 08:08:00   2
Length: 5, dtype: float64

Бежать

out_list = [group[1] for group in in_series.groupby(label_series.values)]

который возвращает out_list list из двух pd.Series:

[2019-07-01 08:00:00   -0.10
2019-07-01 08:02:00   1.16
Length: 2, dtype: float64,
2019-07-01 08:04:00    0.69
2019-07-01 08:06:00   -0.81
2019-07-01 08:08:00   -0.64
Length: 3, dtype: float64]

Обратите внимание, что вы можете использовать некоторые параметры из самого in_series для группировки серий, например, in_series.index.day

Ответ 10

У меня была похожая проблема. У меня был временной ряд ежедневных продаж для 10 разных магазинов и 50 разных товаров. Мне нужно было разделить исходный фрейм данных на 500 фреймов (10 магазинов * 50 магазинов), чтобы применить модели машинного обучения к каждому из них, и я не мог сделать это вручную.

Это глава dataframe:

head of the dataframe: df

Я создал два списка; один для имен фреймов данных и один для пары массивов [item_number, store_number].

    list=[]
    for i in range(1,len(items)*len(stores)+1):
    global list
    list.append('df'+str(i))

    list_couple_s_i =[]
    for item in items:
          for store in stores:
                  global list_couple_s_i
                  list_couple_s_i.append([item,store])

И как только два списка готовы, вы можете зациклить их, чтобы создать нужные кадры данных:

         for name, it_st in zip(list,list_couple_s_i):
                   globals()[name] = df.where((df['item']==it_st[0]) & 
                                                (df['store']==(it_st[1])))
                   globals()[name].dropna(inplace=True)

Таким образом, я создал 500 фреймов данных.

Надеюсь, это будет полезно!