Как создавать файлы из объекта groupby на основе длины фрейма данных

#python #pandas #loops #for-loop #group-by

#python #pandas #циклы #for-цикл #группировать по

Вопрос:

У меня есть фрейм данных (df), который выглядит следующим образом (сильно упрощенный):

 ID  A   B   C   VALUE
1   10  462 2241    217
2   11  498 6953    217
3   67  120 6926    654
4   68  898 7153    654
5   87  557 4996    654
6   88  227 6475    911
7   47  875 5097    911
8   48  143 8953    111
9   65  157 4470    111
10  66  525 9328    111
 

'VALUE' Столбец содержит переменное количество строк с одинаковыми значениями. Я пытаюсь вывести серию файлов csv, которые содержат все строки, содержащие 'VALUE' длину == 2, == 3 и т.д. Например:

 to_csv('/Path/to/VALUE_len_2.csv')              
ID  A   B   C      VALUE
1   10  462 2241    217
2   11  498 6953    217
6   88  227 6475    911
7   47  875 5097    911
to_csv('/Path/to/VALUE_len_3.csv')              
ID  A   B   C      VALUE
3   67  120 6926    654
4   68  898 7153    654
5   87  557 4996    654
to_csv('/Path/to/VALUE_len_4.csv')              
ID  A   B   C      VALUE
7   47  875 5097    111
8   48  143 8953    111
9   65  157 4470    111
10  66  525 9328    111
 

Я могу получить желаемый вывод одного значения длины за раз, например, используя:

 df = pd.concat(v for _, v in df.groupby("VALUE") if len(v) == 2)
df.to_csv("/Path/to/VALUE_len_2.csv")
 

Однако у меня есть десятки значений для тестирования. Я хотел бы поместить это в цикл for порядка:

 mylist = [2,3,4,5,6,7,8,9] or len([2,3,4,5,6,7,8,9])
grouped = df.groupby(['VALUE'])
output = '/Path/to/VALUE_len_{}.csv'

for loop here:
    if item in my list found in grouped:
        output rows to csv
    else:
        pass
 
  • Я пробовал различные конструкции для итерации объекта groupby, используя элементы в списке, и я не смог заставить что-либо работать.
  • Это может быть проблемой при попытке использовать объект groupby таким образом, но более чем вероятно, что это моя неспособность получить правильный синтаксис для завершения итерации.

Ответ №1:

  • Не имеет смысла использовать заранее определенный список для создания имен файлов.
  • df_len будет использоваться для создания имени файла с использованием f-string .
  • Path.exists() используется для определения, существует ли файл или нет
 import pandas as pd
from pathlib import Path

# test data
data = {'ID': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'A': [10, 11, 67, 68, 87, 88, 47, 48, 65, 66], 'B': [462, 498, 120, 898, 557, 227, 875, 143, 157, 525], 'C': [2241, 6953, 6926, 7153, 4996, 6475, 5097, 8953, 4470, 9328], 'VALUE': [217, 217, 654, 654, 654, 911, 911, 111, 111, 111]}
df = pd.DataFrame(data)

# groupby value
for group, data in df.groupby('VALUE'):
    
    # get the length of the dataframe
    df_len = len(data)
    
    # create a filename with df_len
    file = Path(f'/path/to/VALUE_len_{df_len}.csv')
    
    # if the file exists, append without the header
    if file.exists():
        data.to_csv(file, index=False, mode='a', header=False)
        
    # create a new file
    else:
        data.to_csv(file, index=False) 
 

  • Если вам необходимо создать файл только для фреймов данных определенной длины
 desired_length = [2, 3, 4, 5, 6, 7, 8, 9]

# groupby value
for group, data in df.groupby('VALUE'):
    
    # get the length of the dataframe
    df_len = len(data)
    
    # create a filename with df_len
    file = Path(f'/path/to/VALUE_len_{df_len}.csv')
    
    # check if the length of the dataframe is in the desired length
    if df_len in desired_length:
        
        # if the file exists, append without the header
        if file.exists():
            data.to_csv(file, index=False, mode='a', header=False)

        # create a new file
        else:
            data.to_csv(file, index=False)
 

Комментарии:

1. Большое вам спасибо! Я вижу ошибку в своей логике с моими предыдущими попытками. Я хотел создать файл фреймов данных определенной длины, чтобы сэкономить время обработки и место на диске, поскольку в этом наборе данных 800,000 строк потенциально может быть 3K длины, и мне периодически будет просто нужно подмножество. Я также признателен за редактирование заголовка моего вопроса, чтобы сделать его более значимым. Еще раз спасибо.

2. @2kb Добро пожаловать. Я рад, что это работает для вас.

Ответ №2:

 # find the VALUE_len of every VALUE first
df['VALUE_len'] = df.groupby('VALUE')['ID'].transform('count')
cols = df.columns[:-1]
# ['ID', 'A', 'B', 'C', 'VALUE']

# save group by VALUE_len
for VALUE_len, group in df.groupby('VALUE_len'):
    file = Path(f'/path/to/VALUE_len_{VALUE_len}.csv')
    group[cols].to_csv(file, index=False)