Convert str to NaiveDate datatype in rust polars

huangapple go评论95阅读模式
英文:

Convert str to NaiveDate datatype in rust polars

问题

我需要将一系列字符串值转换为 Polars 日期格式。

使用文档作为灵感: https://pola-rs.github.io/polars-book/user-guide/concepts/data-structures/#dataframe,我编写了以下函数:

  1. pub fn convert_str_to_date(s: Series) -> Option<Series> {
  2. Some(
  3. s.iter()
  4. .map(|v| {
  5. let date = v.to_string().replace(",", "").replace("\\\"", "");
  6. let year = &date[0..4];
  7. let month = &date[4..6];
  8. let day = &date[6..8];
  9. NaiveDate::from_ymd_opt(year.parse::<i32>().unwrap(), month.parse::<u32>().unwrap(), day.parse::<u32>().unwrap()).unwrap()
  10. }).collect()
  11. )
  12. }

为了验证函数是否正常工作,我编写了这个测试:

  1. #[test]
  2. fn test_convert_str_to_date() {
  3. let test_s = Series::new("", &["20230101", "20230630", "20220229"]);
  4. let transformed_s = convert_str_to_date(test_s).unwrap();
  5. let expected_s = Series::new(
  6. "",
  7. &[NaiveDate::from_ymd_opt(2023, 1, 1).unwrap(), NaiveDate::from_ymd_opt(2023, 6, 30).unwrap(), NaiveDate::from_ymd_opt(2022, 2, 29).unwrap()],
  8. );
  9. assert_eq!(transformed_s, expected_s);
  10. }

我期望测试通过。然而,我从编译器接收到以下错误:

  1. error[E0277]: a value of type `polars::prelude::Series` cannot be built from an iterator over elements of type `NaiveDate`
  2. --> src/transform.rs:106:16
  3. |
  4. 106 | }).collect()
  5. | ^^^^^^^ value of type `polars::prelude::Series` cannot be built from `std::iter::Iterator<Item=NaiveDate>`
  6. |
  7. = help: the trait `FromIterator<NaiveDate>` is not implemented for `polars::prelude::Series`
  8. = help: the following other types implement trait `FromIterator<A>`:
  9. <polars::prelude::Series as FromIterator<&'a bool>>
  10. <polars::prelude::Series as FromIterator<&'a f32>>
  11. <polars::prelude::Series as FromIterator<&'a f64>>
  12. <polars::prelude::Series as FromIterator<&'a i32>>
  13. <polars::prelude::Series as FromIterator<&'a i64>>
  14. <polars::prelude::Series as FromIterator<&'a str>>
  15. <polars::prelude::Series as FromIterator<&'a u32>>
  16. <polars::prelude::Series as FromIterator<&'a u64>>
  17. and 15 others
  18. note: the method call chain might not have had the expected associated types
英文:

I need to convert a Series of str values to Polars Date format.

Using the documentation as inspiration: https://pola-rs.github.io/polars-book/user-guide/concepts/data-structures/#dataframe, I've written the following function:

  1. pub fn convert_str_to_date(s: Series) -&gt; Option&lt;Series&gt; {
  2. Some(
  3. s.iter()
  4. .map(|v| {
  5. let date = v.to_string().replace(&quot;,&quot;, &quot;&quot;).replace(&quot;\&quot;&quot;, &quot;&quot;);
  6. let year = &amp;date[0..4];
  7. let month = &amp;date[4..6];
  8. let day = &amp;date[6..8];
  9. NaiveDate::from_ymd_opt(year.parse::&lt;i32&gt;().unwrap(), month.parse::&lt;u32&gt;().unwrap(), day.parse::&lt;u32&gt;().unwrap()).unwrap()
  10. }).collect()
  11. )
  12. }

To validate the function is working, I've written this test:

  1. #[test]
  2. fn test_convert_str_to_date() {
  3. let test_s = Series::new(&quot;&quot;, &amp;[&quot;20230101&quot;, &quot;20230630&quot;, &quot;20220229&quot;]);
  4. let transformed_s = convert_str_to_date(test_s).unwrap();
  5. let expected_s = Series::new(
  6. &quot;&quot;,
  7. &amp;[NaiveDate::from_ymd_opt(2023, 1, 1).unwrap(), NaiveDate::from_ymd_opt(2023, 6, 30).unwrap(), NaiveDate::from_ymd_opt(2022, 2, 29).unwrap()],
  8. );
  9. assert_eq!(transformed_s, expected_s);
  10. }

I expect the test to pass. However, I receive the following error from the compiler:

  1. error[E0277]: a value of type `polars::prelude::Series` cannot be built from an iterator over elements of type `NaiveDate`
  2. --&gt; src/transform.rs:106:16
  3. |
  4. 106 | }).collect()
  5. | ^^^^^^^ value of type `polars::prelude::Series` cannot be built from `std::iter::Iterator&lt;Item=NaiveDate&gt;`
  6. |
  7. = help: the trait `FromIterator&lt;NaiveDate&gt;` is not implemented for `polars::prelude::Series`
  8. = help: the following other types implement trait `FromIterator&lt;A&gt;`:
  9. &lt;polars::prelude::Series as FromIterator&lt;&amp;&#39;a bool&gt;&gt;
  10. &lt;polars::prelude::Series as FromIterator&lt;&amp;&#39;a f32&gt;&gt;
  11. &lt;polars::prelude::Series as FromIterator&lt;&amp;&#39;a f64&gt;&gt;
  12. &lt;polars::prelude::Series as FromIterator&lt;&amp;&#39;a i32&gt;&gt;
  13. &lt;polars::prelude::Series as FromIterator&lt;&amp;&#39;a i64&gt;&gt;
  14. &lt;polars::prelude::Series as FromIterator&lt;&amp;&#39;a str&gt;&gt;
  15. &lt;polars::prelude::Series as FromIterator&lt;&amp;&#39;a u32&gt;&gt;
  16. &lt;polars::prelude::Series as FromIterator&lt;&amp;&#39;a u64&gt;&gt;
  17. and 15 others
  18. note: the method call chain might not have had the expected associated types

答案1

得分: 0

polarsSeries 上没有针对 NaiveDate 迭代器的 FromIterator 实现。

你可以使用 From<Logical<DateType, Int32Type>>Series 上实现,然后将迭代器传递给 Logical::from_naive_date,然后将其转换为 Series

  1. pub fn convert_str_to_date(s: Series) -> Option<Series> {
  2. Some(
  3. Logical::from_naive_date(
  4. "column_name",
  5. s.iter().map(|v| {
  6. let date = v.to_string().replace(",", "").replace("\"", "");
  7. let year = &date[0..4];
  8. let month = &date[4..6];
  9. let day = &date[6..8];
  10. NaiveDate::from_ymd_opt(
  11. year.parse::<i32>().unwrap(),
  12. month.parse::<u32>().unwrap(),
  13. day.parse::<u32>().unwrap(),
  14. )
  15. .unwrap()
  16. }),
  17. )
  18. .into(),
  19. )
  20. }

或者,你可以将 NaiveDate 收集到一个 Vec 中,然后使用 Series::new 构造 Series

  1. pub fn convert_str_to_date2(s: Series) -> Option<Series> {
  2. let naive_dates: Vec<_> = s
  3. .iter()
  4. .map(|v| {
  5. let date = v.to_string().replace(",", "").replace("\"", "");
  6. let year = &date[0..4];
  7. let month = &date[4..6];
  8. let day = &date[6..8];
  9. NaiveDate::from_ymd_opt(
  10. year.parse::<i32>().unwrap(),
  11. month.parse::<u32>().unwrap(),
  12. day.parse::<u32>().unwrap(),
  13. )
  14. .unwrap()
  15. })
  16. .collect();
  17. Some(Series::new("column_name", &naive_dates))
  18. }
英文:

polars does not have a FromIterator implementation on Series from an iterator of NaiveDates.

From&lt;Logical&lt;DateType, Int32Type&gt;&gt; is implemented on Series so you can pass the iterator to Logical::from_naive_date and then convert it to a Series:

  1. pub fn convert_str_to_date(s: Series) -&gt; Option&lt;Series&gt; {
  2. Some(
  3. Logical::from_naive_date(
  4. &quot;column_name&quot;,
  5. s.iter().map(|v| {
  6. let date = v.to_string().replace(&quot;,&quot;, &quot;&quot;).replace(&quot;\&quot;&quot;, &quot;&quot;);
  7. let year = &amp;date[0..4];
  8. let month = &amp;date[4..6];
  9. let day = &amp;date[6..8];
  10. NaiveDate::from_ymd_opt(
  11. year.parse::&lt;i32&gt;().unwrap(),
  12. month.parse::&lt;u32&gt;().unwrap(),
  13. day.parse::&lt;u32&gt;().unwrap(),
  14. )
  15. .unwrap()
  16. }),
  17. )
  18. .into(),
  19. )
  20. }

Alternatively, you can collect the NaiveDates into a Vec, and then use Series::new to construct the Series:

  1. pub fn convert_str_to_date2(s: Series) -&gt; Option&lt;Series&gt; {
  2. let naive_dates: Vec&lt;_&gt; = s
  3. .iter()
  4. .map(|v| {
  5. let date = v.to_string().replace(&quot;,&quot;, &quot;&quot;).replace(&quot;\&quot;&quot;, &quot;&quot;);
  6. let year = &amp;date[0..4];
  7. let month = &amp;date[4..6];
  8. let day = &amp;date[6..8];
  9. NaiveDate::from_ymd_opt(
  10. year.parse::&lt;i32&gt;().unwrap(),
  11. month.parse::&lt;u32&gt;().unwrap(),
  12. day.parse::&lt;u32&gt;().unwrap(),
  13. )
  14. .unwrap()
  15. })
  16. .collect();
  17. Some(Series::new(&quot;column_name&quot;, &amp;naive_dates))
  18. }

答案2

得分: 0

以下是代码的翻译部分:

  1. pub fn convert_str_to_date(s: &Series) -> Result<Series, PolarsError> {
  2. let mut s = s
  3. .utf8()?
  4. .replace_all(",|", "")?
  5. .as_date(Some("%Y%m%d"), true)?
  6. .into_series();
  7. s.rename("column_name");
  8. Ok(s)
  9. }
  10. fn main() {
  11. let test_s = Series::new("", &["2023,0101", "202306,30", "20220229"]);
  12. let transformed_s = convert_str_to_date(&test_s).unwrap();
  13. println!("{:?}", transformed_s);
  14. }
  1. 形状: (3,)
  2. Series: 'column_name' [日期]
  3. [
  4. 2023-01-01
  5. 2023-06-30
  6. 空值
  7. ]
英文:

Simpler than the accepted answer:

  1. pub fn convert_str_to_date(s: &amp;Series) -&gt; Result&lt;Series, PolarsError&gt; {
  2. let mut s = s
  3. .utf8()?
  4. .replace_all(r#&quot;,|&quot;&quot;#, &quot;&quot;)?
  5. .as_date(Some(&quot;%Y%m%d&quot;), true)?
  6. .into_series();
  7. s.rename(&quot;column_name&quot;);
  8. Ok(s)
  9. }
  10. fn main() {
  11. let test_s = Series::new(&quot;&quot;, &amp;[&quot;2023,0101&quot;, &quot;202306,30&quot;, &quot;20220229&quot;]);
  12. let transformed_s = convert_str_to_date(&amp;test_s).unwrap();
  13. println!(&quot;{:?}&quot;, transformed_s);
  14. }
  1. shape: (3,)
  2. Series: &#39;column_name&#39; [date]
  3. [
  4. 2023-01-01
  5. 2023-06-30
  6. null
  7. ]

huangapple
  • 本文由 发表于 2023年5月21日 08:47:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/76297868.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定