代码之家  ›  专栏  ›  技术社区  ›  Banana jqurious

Pandas只将具有复杂数据的列划分为实部和虚部

  •  1
  • Banana jqurious  · 技术社区  · 1 年前

    我是熊猫的新手,正在尝试使用包含复杂数值数据和其他一些东西(字符串等)的数据帧

    我所说的精简版:

    import numpy as np
    import pandas as pd
    a = np.array([
            [0.1 + 1j, 0.2 + 0.2j, 0.2, 0.1j, "label_a", 1],
            [0.1 + 1j, 0.5 + 1.2j, 0.5, 1.0j, "label_b", 3],
        ])
    columns = np.array([-12, -10, 10, 12, "label", "number"])
    df = pd.DataFrame(data=a, columns=columns)
    

    为了持久地保存和读取到磁盘,我需要将复数值分为实数和虚数,因为显然没有任何相关的磁盘格式(hdf5、parquet等)支持复数。

    现在,如果数据帧包含 只有 复数,我可以通过引入多索引来做到这一点,这是其他问题已经涵盖的内容(例如。 Modify dataframe with complex values into a new multiindexed dataframe with real and imaginary parts using pandas )。

    # save to file
    pd.concat(
        [df.apply(np.real), df.apply(np.imag)],
        axis=1,
        keys=("R", "I"),
    ).swaplevel(0, 1, 1).sort_index(axis=1).to_parquet(file)
    
    # read from file
    df = pd.read_parquet(file)
    real = df.loc[:, (slice(None), "R")].droplevel(1, axis=1)
    imag = df.loc[:, (slice(None), "I")].droplevel(1, axis=1)
    df = real + 1j * imag
    

    然而,这种方法在存在例如字符串字段的情况下会崩溃。

    我目前正在将数据帧拆分为一个只包含复数的数据帧(即这里的前四列)和其他数据帧。然后我将上述方法应用于前者,与后者合并并保存到文件中。这是有效的,但不是特别好,尤其是当列的顺序没有那么整齐时。

    我希望有更多熊猫经验的人能有一个更简单的方法来实现这一点。若重要的话:就性能而言,我不关心写入,但我关心从文件读取回数据帧。

    1 回复  |  直到 1 年前
        1
  •  1
  •   mozway    1 年前

    您可以处理您知道很复杂的列,也可以独立处理其他列。为其他列添加一个伪第二级:

    N = 4
    cols = df.columns[:N] # or define an explicit list of names
    
    # ensure the type is complex
    # you might need to adjust to other types (np.complex128, np.complex256…)
    tmp = df[cols].astype(np.complex64)
    
    (pd.concat(
        # slice the complex columns
        # NB. using a more efficient way to get the real/imaginary parts
        [pd.DataFrame(np.real(tmp), index=tmp.index, columns=cols),
         pd.DataFrame(np.imag(tmp), index=tmp.index, columns=cols),
        ],
        axis=1,
        keys=("R", "I"),
              )
       # add the other columns
       .join(pd.concat({None: df[df.columns.difference(cols)]}, axis=1))
       .swaplevel(0, 1, 1).sort_index(axis=1)
       .to_parquet('test_pqt')
    )
    

    阅读

    # read from file
    df = pd.read_parquet('test_pqt')
    
    N = 4
    cols = df.columns.get_level_values(0)[:N] # or define an explicit list of names
    
    other_cols = df.columns.get_level_values(0).difference(cols)
    
    real = df.loc[:, (cols, "R")].droplevel(1, axis=1)
    imag = df.loc[:, (cols, "I")].droplevel(1, axis=1)
    df = (real + 1j * imag).join(df.droplevel(1, axis=1)[other_cols])
    
    print(df)
    

    输出:

            -10       -12   10   10   12   12    label number
    0  0.2+0.2j  0.1+1.0j  0.0  0.2  0.1  0.0  label_a      1
    1  0.5+1.2j  0.1+1.0j  0.0  0.5  1.0  0.0  label_b      3
    
        2
  •  0
  •   ragas    1 年前

    替代方法:

    import numpy as np
    import pandas as pd
    
    tmp = df[cols].astype(np.complex64)
    for col in tmp:
    
        col1 = col + "_1"
        col2 = col + "_2"
        df[[col1, col2]] = df[col].str.split('+',expand = True)