【问题标题】:Converting (numeric) strings in column rows, getting max/min of these strings in each row转换列行中的(数字)字符串,获取每行中这些字符串的最大值/最小值
【发布时间】:2021-07-14 02:56:20
【问题描述】:

所以我有一个大型的每日温度数据数据框,我一直在过滤和处理这些数据。 '#Above' 列表示当天在该纬度/经度点(未显示日期,仅保留年份),温度高于阈值。 '#Below' 相同,但低于阈值。如果任何一个事件持续 5 天或更长时间,则将其视为单个事件。例如,在下面的第一行中,有高于和低于相应阈值的天数,但不足以称为天数或事件。但是,在第二行中,您会看到 2 个 5 天的事件,每个事件对应于 2 个单独的“#Mevents”,5+5=10 '#Mdays',并且在“所有事件”中列为两个 5。

    Lat     Lon     Year    #Above  #Mdays   #Mevents   #Below  #Cdays    #Cevents    All Events
44  24.125  262.375 1983    1       0        0          -4       0        0           []
45  24.125  262.375 1985    12      10       2          -25     -20       2           [ 5, -7, -13, 5]  
46  24.125  262.375 1986    30      24       2          -16     -5        1           [12, 12, -5]
47  24.125  262.375 1987    5       0        0          -41     -26       2           [-26, -8]
... ... ... ... ... ... ... ... ... ... ...

这是我一直在使用的循环。 (PS运行需要1.5小时,有什么优化技巧告诉我>_>)
大约有 500 个点,365 天 * 40 年的数据,所以最终会很多。

more_data = pd.DataFrame([])
for iii in cdo_gom.lat.values:
    for jjj in cdo_gom.lon.values:
        for yyyy in np.arange(1981, 2022):
            point = master_df.loc[(master_df['lat'] == iii) & (master_df['lon'] == jjj)]
            year = point.loc[(point['year'] == yyyy)]
            a = np.asarray(year['threshold'].groupby(year['threshold'].diff().ne(0).cumsum()).cumsum())
            MHW = np.count_nonzero(a >= 5)
            above = np.count_nonzero(a >= 1)
            CS = np.count_nonzero(a <= -5)
            below = np.count_nonzero(a <= -1)

            events = a[np.argwhere(np.abs(a-np.roll(a,-1)) >= 5)].reshape(-1)
            hw_events = np.sum(np.array(events) >= 0, axis=0)
            cs_events = np.sum(np.array(events) <= 0, axis=0)

            elist = np.array2string(events, separator=', ')

            more_data = more_data.append(pd.DataFrame({'Lat' : iii, 
                                                       'Lon' : jjj, 
                                                        'Month' : mmm,
                                                        'Year' : yyyy,
                                                        '#MHW days' : MHW + (4*hw_events),
                                                        '#MHW events' : hw_events,
                                                        '#CS days' : CS + (4*cs_events),
                                                        '#CS events' : cs_events,
                                                        'Threshold duration Events' : elist}, 
                                                        index=[0]), ignore_index = True)

我尝试了不同的方法来获取“所有事件”的最大值和最小值,例如 maxCS1 = np.min(events) 但我不断收到 ValueError: zero-size array to reduction没有身份的操作 fmax。
然后我试图获取“所有事件”列本身中每一行的最大值/最小值(TypeError:“float”对象不可迭代)或将最大值/最小值应用于列(相同的 TypeError)。

我不应该从数组转换为字符串(从“事件”变量转换为“名单”变量)吗?我还能如何列出所有事件以及每行的最大值/最小值?

抱歉,有任何不清楚的地方。我很乐意回答任何问题。

我想要什么:

    Lat     Lon     Year    #Above  #Mdays   #Mevents   #Below  #Cdays    #Cevents   All Events       MaxM     MaxC 
0   24.125  262.375 1983    1       0        0          -4       0        0          []     
1   24.125  262.375 1985    12      10       2          -25     -20       2          [ 5, -7, -13, 5] 5        -13
2   24.125  262.375 1986    30      24       2          -16     -5        1          [12, 12, -5]     12       -5
3   24.125  262.375 1987    5       0        0          -41     -26       2          [-26, -8]                 -26
... ... ... ... ... ... ... ... ... ... ...

【问题讨论】:

标签: python pandas numpy


【解决方案1】:

答案可能取决于您的“所有事件”列是什么数据类型。例如,

import pandas as pd

df = pd.DataFrame({"a": ["a", "b", "c"], "events":[
    [7,13,-2],
    [11,-9,12],
    [4,6,8],
]})

type(df.events[0])

...为您提供list 类型的元素。您可以像这样直接应用 min 和 max:

df.events.apply(min)

0   -2
1   -9
2    4
Name: events, dtype: int64

Pandas 将缺失数据表示为 NaN,这是一个特殊的浮点值。这可能是您看到的 TypeErrors 的来源。

查看您的代码,您的事件看起来像是 numpy 数组?所以你有这样的东西:

import numpy as np

df = pd.DataFrame({"a": ["a", "b", "c", "d"], "events":[
    np.array([7,13,-2]),
    np.array([11,-9,12]),
    np.array([4, 6, 8, 15]),
    float("NaN")
]})

要处理 NaN 的可能性,您需要以下内容:

df["MinEvent"] = df.events.apply(lambda x:min(x) if isinstance(x, np.ndarray) else x)

df

    a   events        MinEvent
0   a   [7, 13, -2]     -2.0
1   b   [11, -9, 12]    -9.0
2   c   [4, 6, 8, 15]   4.0
3   d   NaN             NaN

如果您想检查 NaN 或更广泛定义的缺失数据,isna a.k.a isnull 会派上用场:

df.events.isnull().value_counts()

False    3
True     1
Name: events, dtype: int64

最后,通过逐行附加来构建DataFrame 真的很慢。创建整列会更快,或者尝试使用所有行和列名列表的构造函数形式:pd.DataFrame(list_of_rows, columns=['A', 'B', 'C', ...])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 2022-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-04
    • 1970-01-01
    相关资源
    最近更新 更多