由于我不确定确切的术语-假设我有此文件:
dataA.csv:
event,car,bike,bus 63175,,18, 65641,45,9, 65805,,,54 68388,,65, 68388,,,39 73041,7,,18 79336,,44, 79423,,,5
用
dataA = pd.read_csv("dataA.csv", dtype='Int64')
阅读此书,我们得到一个熊猫DataFrame:
dataA: event car bike bus 0 63175 <NA> 18 <NA> 1 65641 45 9 <NA> 2 65805 <NA> <NA> 54 3 68388 <NA> 65 <NA> 4 68388 <NA> <NA> 39 5 73041 7 <NA> 18 6 79336 <NA> 44 <NA> 7 79423 <NA> <NA> 5
有两行,其中“事件”列具有相同的值(我称之为“重复项”:]
3 68388 <NA> 65 <NA> 4 68388 <NA> <NA> 39
...并且我希望将它们“压缩”成一个单行(这是正确的词吗?),以便存在实际值(如果有),而不是NaN(即NA):
3 68388 <NA> 65 39
从How to compact a merge between two Pandas Dataframes with NaN and duplicate join keys?中我得到了答案,我应该使用
.groupby(...).first()
-实际上,它可以工作;此脚本:
#!/usr/bin/env python3 import pandas as pd print(pd.__version__) # 1.0.2 for me dataA = pd.read_csv("dataA.csv", dtype='Int64') print("dataA:") print(dataA) # make sure Pandas prints entirety of DataFrame pd.set_option('display.max_rows', None) pd.set_option('display.max_columns', None) pd.set_option('display.width', None) pd.set_option('display.max_colwidth', None) dataCompact = dataA.groupby('event').first() ##*** print("\ndataCompact:") print(dataCompact)
最终打印:
dataCompact: car bike bus event 63175 <NA> 18 <NA> 65641 45 9 <NA> 65805 <NA> <NA> 54 68388 <NA> 65 39 73041 7 <NA> 18 79336 <NA> 44 <NA> 79423 <NA> <NA> 5
...这就是我想要的,因此可以使用。
但是,仔细观察,我意识到我并不真正理解它是如何工作的-也就是说,在这种情况下,我无法真正分辨出.first()
具体指的是什么; https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.first.html对我没有多大帮助,因为它指出“ 基于日期偏移量对时间序列数据的初始时期进行子集化的方法。
所以,我做了一些实验-基本上在上面的代码中更改了标有##***
的行,并查看了打印输出。
首先,如果我改用此行:
dataCompact = dataA.groupby('event').apply(lambda x: "{} ({}): {}".format(type(x), len(x), x.values.tolist())) ##***
...我得到此打印输出:
dataCompact: event 63175 <class 'pandas.core.frame.DataFrame'> (1): [[63175, <NA>, 18, <NA>]] 65641 <class 'pandas.core.frame.DataFrame'> (1): [[65641, 45, 9, <NA>]] 65805 <class 'pandas.core.frame.DataFrame'> (1): [[65805, <NA>, <NA>, 54]] 68388 <class 'pandas.core.frame.DataFrame'> (2): [[68388, <NA>, 65, <NA>], [68388, <NA>, <NA>, 39]] 73041 <class 'pandas.core.frame.DataFrame'> (1): [[73041, 7, <NA>, 18]] 79336 <class 'pandas.core.frame.DataFrame'> (1): [[79336, <NA>, 44, <NA>]] 79423 <class 'pandas.core.frame.DataFrame'> (1): [[79423, <NA>, <NA>, 5]] dtype: object
[据此,我收集到-本质上,
groupby('event')
为'event'列的每个唯一值提供一个DataFrame:
因此,.first()
必须采用N> = 1行作为输入的DataFrame,并返回单行。
但是,这是我开始困惑的地方-我读过.first()
是指返回N> = 1个输入行中的first
<NA>
替换插槽(未定义的值)); -相反,除第一行外的所有其他行都将被删除!那不是这里发生的事情...因此,我尝试通过为.first()
编写自己的Lambda处理程序来模拟.apply()
的功能:
def proc_df_first(x): # here we get a DataFrame with single row, if "event" (groupby arg) is a unique value; # or a DataFrame with as many rows, as there are repeated rows with "event" of same value ("duplicate") if len(x) == 1: return x elif len(x) > 1: # create empty return DataFrame (eventually it will only have a single row) retdf = pd.DataFrame(columns = x.columns) #return retdf # is empty, so is skipped in final result of .groupby.apply # must populate rowdata first, then assign via .loc (SO:17091769) for icol in x.columns: coldata = x[icol] # is Series thisval = pd.NA # initialize the "compact" single value we want to set for this column (eventually derived from all the row values in this column) for idx, val in coldata.iteritems(): #print("***", idx, val, val is pd.NA) # `val is None` is always False; `val==pd.NA` always prints `<NA>`; `val is pd.NA` is correct if thisval is pd.NA: if val is not pd.NA: # found the first non-NA value; save it, and stop looking further thisval = val break # store saved non-NA value into return DataFrame retdf.at[ x.index[0], icol ] = thisval # SO: 13842088 return retdf dataCompact = dataA.groupby('event').apply(lambda x: proc_df_first(x)) ##***
...最终打印:
dataCompact: event car bike bus event 63175 0 63175 <NA> 18 <NA> 65641 1 65641 45 9 <NA> 65805 2 65805 <NA> <NA> 54 68388 3 68388 NaN 65 39 73041 5 73041 7 <NA> 18 79336 6 79336 <NA> 44 <NA> 79423 7 79423 <NA> <NA> 5
...这与
.groupby('event').first()
基本上具有相同的结果(除了重复的“事件”列(是否是层次结构标签?)和索引列)。
所以,这是我的问题:
.first()
返回一组行中的第一个非NA每列值,从而导致该行组的单行表示-这是正确的吗?pd.NA
值时) ?我知道我可以在任何地方执行dataA.groupby('event').apply(lambda x: proc_df_first(x)).astype('Int64')
并获得pd.NA
-但鉴于我已经逐个元素地迭代了整个表,因此我不希望在表上再进行一次循环-只是为了摆脱一个单浮点NaN。如果不确定该特定值,我该怎么办才能确保proc_df_first()
中从.apply()
返回的值始终是pd.NA
值?由于我不确定确切的术语-假设我有这个文件:dataA.csv:event,car,bike,bus 63175,,18,65641,45,9,65805 ,,, 54 68388, ,65,68388 ,,, 39 73041,7,,18 79336,,44,79423 ,,, 5 ...
在熊猫中有2种不同的first
功能,它们是不同的: