Разделение кадра данных на несколько фреймов данных
У меня очень большой фреймворк (около 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 просто запускается навсегда!
Есть ли разумный способ сделать это?
Ответы
Ответ 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 фреймов данных.
Надеюсь, это будет полезно!