csv Python根据条件从多行读取值

am46iovg  于 2023-07-31  发布在  Python
关注(0)|答案(1)|浏览(84)

我有一个csv文件(2个不同的样本)

from io import StringIO
import pandas as pd

dfa = pd.read_csv(StringIO("""
      Date/Time     ID  C_1 C_2  C_3   C_4 C_5 C_6  C_7  C_8 C_9 C_10
"18/06/2023 3:51:53"  136 101 2028  61    4   3   18   0    0   2    2
"18/06/2023 3:51:54"  24  101 2029  65    0   0   0    1    1   NA   1
"18/06/2023 3:51:55"  16  101 2022  89    0   0   0    0    0   NA   7
"18/06/2023 3:51:56"  136 101 2024  90    0   0   0    0    0   NA   3
"18/06/2023 3:51:57"  24  101 2026  87    0   1   8    0    0   9    2
"18/06/2023 3:51:58"  136 101 2023  33    0   1   87   0    0   2    2"""), sep="\s+")

dfb = pd.read_csv(StringIO("""
      Date/Time     ID  C_1  C_2  C_3  C_4 C_5 C_6  C_7  C_8 C_9 C_10
"18/06/2023 3:51:53"  24  101 2029  65    0   0   0    1    1   NA   1
"18/06/2023 3:51:54"  136 101 2028  61    4   3   18   0    0   2    2
"18/06/2023 3:51:55"  16  101 2022  89    0   0   0    0    0   NA   7
"18/06/2023 3:51:56"  136 101 2024  90    0   0   0    0    0   NA   3
"18/06/2023 3:51:57"  136 101 2023  33    0   1   87   0    0   2    2
"18/06/2023 3:51:58"  24  101 2026  87    0   1   8    0    0   9    2"""), sep="\s+")

dfc = pd.read_csv(StringIO("""
      Date/Time     ID  C_1 C_2  C_3   C_4 C_5 C_6  C_7  C_8 C_9 C_10
"18/06/2023 3:51:53"  136 101 2028  61    4   3   18   0    0   2    2
"18/06/2023 3:51:54"  24  101 2029  65    0   0   0    1    1   NA   1
"18/06/2023 3:51:54"  136 102 2045  61    2   3   4    5    6   7    8
"18/06/2023 3:51:55"  16  101 2022  89    0   0   0    0    0   NA   7
"18/06/2023 3:51:56"  136 101 2024  90    0   0   0    0    0   NA   3
"18/06/2023 3:51:56"  16  102 2022  89    0   0   0    0    0   NA   11
"18/06/2023 3:51:56"  136 101 2024  90    0   0   0    0    0   NA   3
"18/06/2023 3:51:57"  24  101 2026  87    0   1   8    0    0   9    2
"18/06/2023 3:51:58"  24  102 2045  44    43  42  41   40   39  38   37
"18/06/2023 3:51:59"  136 101 2023  33    0   1   87   0    0   2    2"""), sep="\s+")

字符串
我试图读取行值(几列)使用以下条件-

  • 检查ID ='16',如果匹配,读取'日期/时间'、'C_1'和'C_10'列值。
  • 找到ID ='136'的第一个前一行位置(从ID ='16'开始),并读取从C_2到C_8的列值。
  • 找到第一个前一个或第一个下一个(从ID ='16')行位置,其中ID ='24',并读取'C_9'列值(2行中不为空的一行,或如果两行都为空,则留空)。

输出-

Date/Time     ID  C_1  C_2   C_3  C_4 C_5 C_6  C_7  C_8 C_9 C_10
18/06/2023  3:51:55 16  101  2028   61   4   3   18   0    0   9   7

vybvopom

vybvopom1#

如果我理解正确的话,将三种可能性进行切片,使用maskffill/bfill,然后聚合为一行groupby.first

m = df['ID'].eq('16')
m1 = df['ID'].isin(['16', '136'])
m2 = df['ID'].isin(['16', '24'])

cols = ['Date/Time', 'ID', 'C_1', 'C_10']

pd.concat([df.loc[m1].mask(m).ffill().loc[m, cols+['C_2', 'C_3', 'C_4', 'C_5', 'C_6', 'C_7', 'C_8']],
           df.loc[m2].mask(m).ffill().loc[m, cols+['C_9']],
           df.loc[m2].mask(m).bfill().loc[m, cols+['C_9']],
          ]).groupby(level=0).first()

字符串

  • 注:优先级由concat中切片的顺序给出,第一个非NaN值将被保留。此外,如果C_1/C_2中有多个可能的值,则应将ffill/bfill替换为.groupby(['ID', 'C_1', 'C_10']).ffill()/bfill()

输出量:

Date/Time   ID    C_1  C_10     C_2   C_3  C_4  C_5   C_6  C_7  C_8  C_9
2  18/06/2023 3:51:53  136  101.0   2.0  2028.0  61.0  4.0  3.0  18.0  0.0  0.0  9.0

溶液/C_1组
m = df['ID'].eq('16')
m1 = df['ID'].isin(['16', '136'])
m2 = df['ID'].isin(['16', '24'])

cols = ['Date/Time', 'ID', 'C_1', 'C_10']

tmp = df.mask(m).fillna({'C_1': df['C_1']})

pd.concat([tmp.loc[m1].groupby(df['C_1']).ffill().loc[m, cols+['C_2', 'C_3', 'C_4', 'C_5', 'C_6', 'C_7', 'C_8']],
           tmp.loc[m2].groupby(df['C_1']).ffill().loc[m, cols+['C_9']],
           tmp.loc[m2].groupby(df['C_1']).bfill().loc[m, cols+['C_9']],
          ]).groupby(level=0).first()


输出(使用dfc作为输入):

Date/Time   ID    C_1  C_10     C_2   C_3  C_4  C_5   C_6  C_7  C_8   C_9
3  18/06/2023 3:51:53  136  101.0   2.0  2028.0  61.0  4.0  3.0  18.0  0.0  0.0   9.0
5  18/06/2023 3:51:54  136  102.0   8.0  2045.0  61.0  2.0  3.0   4.0  5.0  6.0  38.0

相关问题