вычисление функции с использованием файлов

#python #function #numpy #for-loop

#python #функция #numpy #for-цикл

Вопрос:

Я написал функцию python для некоторых вычислений, которая использует ниже двух наборов данных.Я хочу вычислить z для всех данных в data_2, используя row1,row2, ror3,row4, row5 из data_1.Однако, поскольку я новичок в python, я попытался написать, но между ними произошел сбой.пожалуйста, помогите.Спасибо.

        data_1                                      data_2        
file    a    b    c    d                             x
file1  0.5  0.6  0.8  0.3                           0.5
file1  0.2  0.2  0.4  0.1                           0.8
file1  0.1  0.4  0.5  0.2                           0.9
  

мой проверенный код здесь:

 import numpy as np
file1=np.loadtxt('data_1',skiprows=1,usecols=(1,2,3))
file2=np.loadtxt('data_2',skiprows=1,usecols=(0))

def calculation(a,b,c,x):
    z=(a b c)*x
    return z

for value in file2:
    print(value)
    calculation
  

мой ожидаемый результат должен быть примерно таким

    data_3                                            
file    a    b    c    d       z                          
file1  0.5  0.6  0.8  0.3      -
file1  0.5  0.6  0.8  0.3      -                     
file1  0.5  0.6  0.8  0.3      -                     
file1  0.2  0.2  0.4  0.1      -
file1  0.2  0.2  0.4  0.1      -                     
file1  0.2  0.2  0.4  0.1      -                        
file1  0.1  0.4  0.5  0.2      -
file1  0.1  0.4  0.5  0.2      -                       
file1  0.1  0.4  0.5  0.2      -                     
  

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

1. 1) удалите «каждый» в вашем цикле for, 2) вы вызываете вычисление без аргументов

2. for each value in file2: недопустимо в python. Это должно быть for value in file2:

3. пожалуйста, покажите мне, если возможно, я обновил код, но результат я получаю не так, как ожидалось

4. У вас смешанные типы данных (строка в первом столбце), с которыми немного проще обращаться, pandas чем напрямую numpy . Можете ли вы использовать пакет pandas?

5. @tdelaney да, я могу

Ответ №1:

Python является динамическим языком и numpy имеет тенденцию переопределять обычные операторы для применения операций ко всем наборам данных. Часто, если у вас есть for цикл, вы не пользуетесь этим преимуществом.

numpy массивы могут содержать только один тип данных, но у вас есть строка в столбце 0. pandas переносит numpy и упрощает работу с несколькими типами данных. Итак, я переключился на чтение pandas.DataFrame объектов вместо массивов.

Похоже, вам нужно декартово произведение file2["x"] со строками file1 . Один из способов сделать это — создать фиктивный столбец в обоих фреймах данных, которые имеют совпадающие значения, а затем объединить. Используйте sum метод for a b c , а затем умножьте на x , и вы получите результат.

 import pandas as pd

# read space separated tables
file1=pd.read_table('data_1', sep=r"s ")
file2=pd.read_table('data_2', sep=r"s ")

# we want (a b c)*x, for each value in file2["x"]. Do the sum, then
# use `merge` with a temporary key to create the cartesian product 
# with x. For each `x`, merge will create a row for each matching
# key and since all keys match, we've got a cartesian product.
# Finally, multiply.
file1["_tmpsums"] = file1[["a", "b", "c"]].sum(axis=1)
file1["_tmpmergekey"] = file2["_tmpmergekey"] = 1
file1 = pd.merge(file1, file2, on="_tmpmergekey")
file1["z"] = file1["_tmpsums"] * file1["x"]
file1 = file1.drop(["_tmpsums", "_tmpmergekey", "x"], axis=1)

print("   data_3")
print(file1.to_string(col_space=6, index=False, justify="center"))
  

Результат

    data_3
 file     a      b      c      d      z  
 file1   0.5    0.6    0.8    0.3   0.95 
 file1   0.5    0.6    0.8    0.3   1.52 
 file1   0.5    0.6    0.8    0.3   1.71 
 file1   0.2    0.2    0.4    0.1   0.40 
 file1   0.2    0.2    0.4    0.1   0.64 
 file1   0.2    0.2    0.4    0.1   0.72 
 file1   0.1    0.4    0.5    0.2   0.50 
 file1   0.1    0.4    0.5    0.2   0.80 
 file1   0.1    0.4    0.5    0.2   0.90 
  

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

1. вывод сильно отличается от моего …. не могли бы вы исправить свой код, чтобы вывод был таким же

2. Я не уверен, насколько отличается. Я изменил формат вывода. Надеюсь, это близко.

3. все еще разные …. мне нужно вычислить функцию для каждого файла значений z a b c d z file1 0.5 0.6 0.8 0.3 — файл1 0.5 0.6 0.8 0.3 — файл1 0.5 0.6 0.8 0.3 — файл1 0.2 0.2 0.4 0.1 — файл1 0.2 0.2 0.4 0.1 — файл1 0.2 0.2 0.4 0.1 — файл1 0.10.4 0.5 0.2 — файл1 0.1 0.4 0.5 0.2 — файл1 0.1 0.4 0.5 0.2 —

4. О, я понимаю. Мне придется немного повозиться с этим.

5. возможно ли это с помощью numpy, пожалуйста, дайте мне знать … мне довольно сложно понять

Ответ №2:

Использование pandas следующим образом

 import pandas as pd

# Load Data
data_1 = pd.read_csv('data_1.txt', delimiter = r"s ")
data_2 = pd.read_csv('data_2.txt', delimiter = r"s ")

# Compute the cartesian product of data_1 with data_2
# since for each row in data_1, we need sequence of rows in data_2
# We do this using DataFrame merge by injecting a key that is repeated for each row
# i.e. 'merge_key'
data_1['merge_key'] = pd.Series([1]*len(data_1))
data_2['merge_key'] = pd.Series([1]*len(data_2))
df = pd.merge(data_1, data_2, on = 'merge_key')
# Drop merge key from result
df.drop('merge_key', axis = 'columns', inplace = True)

# DataFrame df now has columns File, a, b, c, d, x
# We can apply function calulation to each row using apply
# and specifying the columns to send to calculation
df['z'] = df.apply(lambda row: calculation(row['a'], row['b'], row['c'], row['x']), axis = 'columns')

# Drop x column
df.drop('x', axis = 'columns', inplace = True)

# Write to CSV file
df.to_csv('data_3.txt', index=False, sep = " ")
  

Вывод

Pandas DataFrame df

     file    a   b   c   d   z
0   file1   0.5 0.6 0.8 0.3 0.95
1   file1   0.5 0.6 0.8 0.3 1.52
2   file1   0.5 0.6 0.8 0.3 1.71
3   file1   0.2 0.2 0.4 0.1 0.40
4   file1   0.2 0.2 0.4 0.1 0.64
5   file1   0.2 0.2 0.4 0.1 0.72
6   file1   0.1 0.4 0.5 0.2 0.50
7   file1   0.1 0.4 0.5 0.2 0.80
8   file1   0.1 0.4 0.5 0.2 0.90
  

Файл CSV data_3.txt

 file a b c d z
file1 0.5 0.6 0.8 0.3 0.9500000000000001
file1 0.5 0.6 0.8 0.3 1.5200000000000002
file1 0.5 0.6 0.8 0.3 1.7100000000000002
file1 0.2 0.2 0.4 0.1 0.4
file1 0.2 0.2 0.4 0.1 0.6400000000000001
file1 0.2 0.2 0.4 0.1 0.7200000000000001
file1 0.1 0.4 0.5 0.2 0.5
file1 0.1 0.4 0.5 0.2 0.8
file1 0.1 0.4 0.5 0.2 0.9
  

Базовый Python

Тот же вывод

 # Get data from first file
with open('data_1.txt', 'r') as f:
    # first file header
    header1 = f.readline()
    
    # Let's get the lines of data
    data_1 = []
    for line in f:
        new_data = line.rstrip().split()  # strip 'n' and split on parens
        for i in range(1, len(new_data)):
            new_data[i] = float(new_data[i])  # convert columns after file to float
        data_1.append(new_data)
  
# Get data from second file
with open('data_2.txt', 'r') as f:
    # second file header
    header2 = f.readline()
    
    # Let's get the lines of data
    data_2 = []
    for line in f:
        new_data = float(line.rstrip())  # only one value per line
        data_2.append(new_data)


with open('data_3.txt', 'w') as f:
    # Output file
    # Write Header
    f.write("file a b c d zn")
    
    # Use double loop to loop through all rows of data_2 for each row in data_1
    for v1 in data_1:
        # For each row in data_1
        file, a, b, c, d = v1  # unpacking the values in v1 to individual variables
        for v2 in data_2:
            # for each row in data_2
            x = v2  # data2 just has a single value per row
           
            # Calculation using posted formula
            z = calculation(a, b, c, x)
            
            # Write result
            f.write(f"{file} {a} {b} {c} {d} {z}n")
       
  

Версия Numpy

 import numpy as np
file1=np.loadtxt('data_1.txt',skiprows=1,usecols=(1,2,3, 4))
file2=np.loadtxt('data_2.txt',skiprows=1,usecols=(0))

with open('data_3.txt', 'w') as f:
    # Write header
    f.write("file a b c d zn")
    
    # Double loop to through the values of file1 and file2
    for val1 in file1:
        for val2 in file2:
            # Only use first 3 values (val1[:3] to only use first 3 value so ignore d)
            z = calculation(*val1[:3], val2)  # *val[:3] is unpacking values to go into calculation
            # Write result
            # map(str, val1) - converts values to string
            # str(z) converts z to string
            #' '.join([*map(str, val1), str(z)] - creates a space separated string
            f.write(' '.join([*map(str, val1), str(z)])   "n")
  

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

1. это нормально, но где функция, которая вычисляет то же самое

2. возможно ли это с помощью numpy, пожалуйста, дайте мне знать … мне довольно сложно понять

3. @anonymossi — df['z'] = df.apply(lambda row: calculation(row['a'], row['b'], row['c'], row['x']), axis = 'columns') использует вашу функцию вычисления. Поскольку вы заявили, что только начали с Python, я сделаю другую версию, используя более простые функции.

4. @anonymossi — обновлено версией, использующей базовый Python. Имеет ли это смысл?