python-3.x 从单个文件中的多个页面创建一个 Dataframe

3yhwsihp  于 2023-03-31  发布在  Python
关注(0)|答案(1)|浏览(127)

我有一个数据的文本文件,我想把它读入一个Pandas Dataframe 。这个文件看起来像这样:

PAGE 1 ----- DATE --- NAME
TEST 001
MATERIAL A
Angle | Body 1 | Body 2 | Body 3
30    | 123    | 456    | 789
60    | 123    | 456    | 789
90    | 123    | 456    | 789

PAGE 2 ----- DATE --- NAME
TEST 001
MATERIAL A
Angle | Body 4 | Body 5 
30    | 123    | 456
60    | 123    | 456
90    | 123    | 456

PAGE 3 ----- DATE --- NAME
TEST 001
MATERIAL B
Angle | Body 1 | Body 2 | Body 3
30    | 123    | 456    | 789
60    | 123    | 456    | 789
90    | 123    | 456    | 789

每个文件有一个或多个测试和一个或多个材料。不同的测试将有不同数量的Angular 或物体。我想在一个数据框中包含单个测试和材料的所有数据,如下所示:

TEST 001 MATERIAL A
Angle | Body 1 | Body 2 | Body 3 | Body 4 | Body 5
30    | 123    | 456    | 789    | 123    | 456
60    | 123    | 456    | 789    | 123    | 456
90    | 123    | 456    | 789    | 123    | 456

我最初的做法是:

1. Parse the file to find every TEST and MATERIAL.
 2. Create a separate dataframe for each page containing TEST 001 and MATERIAL A
 3. Merge those dataframes on Angle 
 4. Continue iterating through each TEST-MATERIAL combo in the file.

这或多或少是可行的,但它非常笨拙和令人困惑,如果我在包含很多测试的文件上使用它会很慢。有没有更好的方法告诉Pandas整理数据,这样我就可以避免在我只想要一个 Dataframe 时制作多个 Dataframe ?我没有选择首先更改数据的结构。

xuo3flqw

xuo3flqw1#

下面是一个使用pandas并借助 * 自定义函数 * 的命题:

def get_tm(test: str, material: str) -> pd.DataFrame:
    df = (pd.read_csv("textfile.txt", header=None, names=["DATA"])
                .loc[lambda x: ~x["DATA"].str.contains("PAGE", na=False)])
​
    m = df["DATA"].str.startswith("TEST")
​
    df["TM_NAME"] = df["DATA"].str.cat(df["DATA"].shift(-1), sep="/").where(m).ffill()
    df["ANG_BODY"] = "ANG_BODY/" + m.shift(2, fill_value=0).cumsum().astype(str)
    
    out = (
            df.loc[~m^m.shift(fill_value=True)]
                .pipe(lambda df_: df_.join(df_.pop("DATA").str.split("\s*\|\s*", expand=True)))
                .loc[lambda df_: df_.pop("TM_NAME") == f"{test}/{material}"]
                .assign(idx= lambda df_: df_.groupby("ANG_BODY").cumcount()+1)
                .pivot(index="idx", columns="ANG_BODY")
                .droplevel(1, axis=1).reset_index(drop=True)
                .pipe(lambda df_: df_.set_axis(df_.iloc[0].str.strip(), axis=1))
                .dropna(axis=1).iloc[1:, 1:].rename_axis(None, axis=1)
                .sort_index(axis=1)
          )
​
    return out
​

输出:

print(get_tm("TEST 001", "MATERIAL A"))
​
  Angle Body 1 Body 2 Body 3 Body 4 Body 5
1    30    123    456    789    123    456
2    60    123    456    789    123    456
3    90    123    456    789    123    456

print(get_tm("TEST 001", "MATERIAL B"))

  Body 1 Body 2 Body 3
1    123    456    789
2    123    456    789
3    123    456    789

相关问题