#python #pandas #loops
#python #pandas #циклы
Вопрос:
У меня есть данные в трех экземплярах, я хочу получить объединенные данные всех трех копий в один фрейм данных, сохраняя позицию значения из каждой строки и столбца. Скажем, среднее значение в столбце 2 строки 3 из всех реплицируемых файлов должно появиться в новом фрейме данных в столбце 2 строки 3. Пример того, как выглядят данные и код, который я пробовал, выглядит следующим образом. Любая помощь приветствуется. Спасибо
data = {}
for file in glob.glob('results/*.csv'):
name = check_output(['basename',file,'.csv']).decode().strip()
data[name] = pd.read_csv(file, index_col = 0, header = 0)
data[name].columns = pd.to_numeric(data[name].columns)
data['file1_A']
A B
1.8 1.7
1.3 1.3
data['file_B']
A B
1.7 1.4
1.9 1.7
data['file_c']
A B
1.2 1.6
2.1 2.9
expected outcome
file1
A B
1.56 1.56
1.76 1.96
i.e.,
A B
(1.8 1.7 1.2)/3 (1.7 1.4 1.6)/3
(1.3 1.9 2.1)/3 (1.3 1.7 2.9)/3
#I usually write the following code for small number samples
file1 = (data['file1_A'] data['file1_B'] data['file1_C'])/3
#I tried to write a loop for large number of samples, but it seems like it is not quite right.
files = ['file1_', 'file2_', 'file3_']
totals = {}
for f in files:
replicates ={}
for sample, df in totals.items():
if f in sample:
replicates[sample] = df
final_df = df/3
Комментарии:
1. обновите форматирование и лучше объясните, что вы хотите, скорее
final_df = df/3
всего, с неправильным отступом
Ответ №1:
Работа с несколькими матрицами — это работа для numpy
! У него есть функция numpy.mean()
, которая принимает среднее значение (= среднее) по нескольким матрицам. Хитрость в том, что вы должны преобразовать свой pandas.DataFrame
в a numpy.array
и обратно. Взгляните на этот пример:
import numpy
import pandas
import random
import itertools
# Given that loading the files isn't the problem, I'll create some dummy data here
data = {
f"file{filenumber}_{filename}": pandas.DataFrame(
[
{
"A": random.random() random.randint(0, 2),
"B": random.random() random.randint(0, 2),
}
for _ in range(2)
]
)
for filenumber, filename in itertools.chain.from_iterable([[(i, l) for l in ["A", "B", "C"]] for i in range(1, 6)])
}
# Loop the files
for filenumber in range(1, 6):
print(f"Processing files that start with: file{filenumber}_")
# Convert all files to numpy arrays
numpy_arrays = [item.to_numpy() for name, item in data.items() if name.startswith(f"file{filenumber}_")]
# Use numpy to take the mean of each cell, across the frames (mean is the same as summing and dividing by the number of elements)
means = numpy.mean(numpy_arrays, axis=0)
# Convert back to a dataframe
df = pandas.DataFrame(means, columns=data[f"file{filenumber}_A"].columns)
# Or in a single line
df = pandas.DataFrame(numpy.mean([item.to_numpy() for name, item in data.items() if name.startswith(f"file{filenumber}_")], axis=0), columns=data[f"file{filenumber}_A"].columns)
print(df)
Комментарии:
1. Большое спасибо за код и разъяснения. Это сработало отлично.
2. @brandnewtoprogramming, рад, что вам это нравится. Пожалуйста, примите ответ, если это то, что вам нужно. Это также помогает другим находить то, что они ищут.
Ответ №2:
Похоже, ответ довольно прост. Вот простой цикл, который работал для получения средней матрицы всех копий.
#load all files into an empty dictionary
data = {}
for file in glob.glob('results/*.csv'):
name = check_output(['basename',file,'.csv']).decode().strip()
data[name] = pd.read_csv(file, index_col = 0, header = 0)
data[name].columns = pd.to_numeric(data[name].columns)
# write a loop to get an average of matrices of replicates
files = ['file1_', 'file2_', 'file3_']
totals = {}
for f in files:
df = (data[f 'A'] data[f 'B'] data[f 'C'])/3
totals[f] = df