【问题标题】:How to pass a function with more than one argument to pandas converters?如何将具有多个参数的函数传递给熊猫转换器?
【发布时间】:2022-08-14 23:58:17
【问题描述】:

我有一个 CSV 文件,需要将其作为 DataFrame 读取,但需要在列中进行一些转换。

这是我文件中的内容(数组以字符串形式出现):

   array1     array2       matrix1                      matrix2  size1  size2
(1, 2, 3)  (4, 5, 6)  (1, 2, 3, 4)  (1, 2, 3, 4, 5, 6, 7, 8, 9)      2      3
(3, 2, 1)  (6, 5, 4)  (4, 3, 2, 1)  (9, 8, 7, 6, 5, 4, 3, 2, 1)      2      3

数组列需要转换为数组,矩阵列需要根据给定的大小转换为矩阵。 (实际过程更复杂,数据中的值实际上对应每个矩阵的下三角。)

因此,预期的输出 DataFrame 是:

      array1     array2                   matrix1                                            matrix2  size1  size2
0  [1, 2, 3]  [4, 5, 6]  [[1.0, 2.0], [3.0, 4.0]]  [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, ...      2      3

1  [3, 2, 1]  [6, 5, 4]  [[4.0, 3.0], [2.0, 1.0]]  [[9.0, 8.0, 7.0], [6.0, 5.0, 4.0], [3.0, 2.0, ...      2      3

我正在使用converters 在读取数组列时对其进行转换。所以,如果我只转换数组:

import numpy as np, pandas as pd

csv_file = \'data.csv\'
array_columns = [\'array1\', \'array2\']
array_converters = dict([(column, lambda x: np.fromstring(x[1:-1], sep=\',\').astype(\'int\')) \\
                          for column in array_columns])
df = pd.read_csv(csv_file, converters=array_converters)

结果是:

            array1           array2       matrix1                      matrix2  size1  size2
0  [1.0, 2.0, 3.0]  [4.0, 5.0, 6.0]  (1, 2, 3, 4)  (1, 2, 3, 4, 5, 6, 7, 8, 9)      2      3

1  [3.0, 2.0, 1.0]  [6.0, 5.0, 4.0]  (4, 3, 2, 1)  (9, 8, 7, 6, 5, 4, 3, 2, 1)      2      3

然后我可以通过这样做来解析矩阵列:

matrix_columns = [(f\'matrix{i}\', f\'size{i}\') for i in range(1, 3)]
for array_str_column, size_column in matrix_columns:
    df[array_str_column] = df.apply(lambda x: array_to_matrix(x[array_str_column], \\
                                    x[size_column]), axis=1)

其中array_to_matrix 是一个函数,它接受数组字符串并将其转换为矩阵:

def array_to_matrix(array_str, size):
    array = np.fromstring(array_str[1:-1], sep=\',\')
    return array.reshape(size, size)

但是,我还没有找到使用转换器解析矩阵的方法。

我尝试过像这样重写 for 循环:

matrix_converters = dict([(array_str_column, df.apply(lambda x: array_to_matrix(x[array_str_column], \\
                x[size_column]), axis=1)) for array_str_column, size_column in matrix_columns])

但是,当然,在调用pd.read_csv 之前不会定义df,我希望随后应用所有转换器(用于数组和矩阵)(我可以将array_convertersmatrix_converters 合并到一个字典中) .

我尝试过以不同的方式传递参数。例如:

matrix_columns = [(f\'matrix{i}\', f\'size{i}\') for i in range(1, 3)]
matrix_converters = dict([(array_str_column, lambda x: array_to_matrix(x, size_column)) \\
                           for array_str_column, size_column in matrix_columns])
df = pd.read_csv(csv_file, converters=matrix_converters) 

问题是lambda中的x只对应第一行的字符串\"(1,2,3,4)\",而不是整行,因此,它不包含任何其他的数据柱子。如何将尺寸传递给函数array_to_matrix

我还尝试使用x, ylambda 添加另一个参数,但我收到错误TypeError: <lambda>() missing 1 required positional argument: \'y\'

    标签: python pandas matrix lambda


    【解决方案1】:

    鉴于您提供的数据框:

    import pandas as pd
    
    df = pd.DataFrame(
        {
            "array1": ["(1, 2, 3)", "(3, 2, 1)"],
            "array2": ["(4, 5, 6)", "(6, 4, 5)"],
            "matrix1": ["(1, 2, 3, 4)", "(4, 3, 2, 1)"],
            "matrix2": ["(1, 2, 3, 4, 5, 6, 7, 8, 9)", "(9, 8, 7, 6, 5, 4, 3, 2, 1)"],
            "size1": [2, 2],
            "size2": [3, 3],
        }
    )
    

    我建议一种不同的方法:

    # Transform strings into lists
    for col in ["array1", "array2", "matrix1", "matrix2"]:
        df[col] = (
            df[col]
            .apply(lambda x: x.strip("(").strip(")").split(", "))
            .apply(lambda x: [int(i) for i in x])
        )
    
    # Convert lists into lists of lists
    for matrix, size in zip(
        [col for col in df.columns if col.startswith("matrix")],
        [col for col in df.columns if col.startswith("size")],
    ):
        df[matrix] = df.apply(
            lambda x: [
                x[matrix][i : i + x[size]] for i in range(0, len(x[matrix]), x[size])
            ],
            axis=1,
        )
    

    以便:

          array1     array2           matrix1                            matrix2  size1  size2
    0  [1, 2, 3]  [4, 5, 6]  [[1, 2], [3, 4]]  [[1, 2, 3], [4, 5, 6], [7, 8, 9]]      2      3
    1  [3, 2, 1]  [6, 4, 5]  [[4, 3], [2, 1]]  [[9, 8, 7], [6, 5, 4], [3, 2, 1]]      2      3
    

    【讨论】:

      猜你喜欢
      • 2014-04-06
      • 1970-01-01
      • 1970-01-01
      • 2017-06-22
      • 2022-01-19
      • 1970-01-01
      • 2012-02-18
      • 2023-04-04
      • 1970-01-01
      相关资源
      最近更新 更多